libsvm代码阅读:svm.cpp浅谈和函数指针

Update:2014-2-26 LinJM  @HQU  『 libsvm专栏地址:http://blog.csdn.net/column/details/libsvm.html 』

svm.cpp浅谈

svm.cpp总共有3159行代码,实现了svm算法的核心功能,里面总共有Cache、Kernel、ONE_CLASS_Q、QMatrix、Solver、Solver_NU、SVC_Q、SVR_Q 8个类(如下图1所示),而它们之间的继承和组合关系如图2、图3所示。在这些类中Cache、Kernel、Solver是核心类,对整个算法起支撑作用。在以后的博文中我们将对这3个核心类做重点注解分析,另外还将对svm.cpp中的svm_train函数做一个注解分析。

图1


 图2


图3


下面先看看svm.cpp的前几行代码,主要是几个inline函数,inline函数解决频繁调用小函数大量消耗栈空间的问题
#include "svm.h"
int libsvm_version = LIBSVM_VERSION;

typedef float Qfloat;
typedef signed char schar;

//inline函数解决频繁调用小函数大量消耗栈空间;static函数为静态函数/或内部函数,指函数的调用范围只局限于本文件
#ifndef min
template <class T> static inline T min(T x,T y) { return (x<y)?x:y; }
#endif
#ifndef max
template <class T> static inline T max(T x,T y) { return (x>y)?x:y; }
#endif
template <class T> static inline void swap(T& x, T& y) { T t=x; x=y; y=t; }

下面这个是clone函数( 一个完全克隆函数,操作结束后,内部的所有数据和指针完全一样),刚开始看的时候对clone的形参T*& dst不太了解,后来才知道这是指针的引用,就是说在函数里面指针的改变等同于形参的改变。关于 memcpy和*&的具体解释我参看我的博文  常见的C++知识 。
template <class S, class T> static inline void clone(T*& dst, S* src, int n)
{
	dst = new T[n];
	memcpy((void *)dst,(void *)src,sizeof(T)*n);
}

下面这个是幂次函数,写得挺好的, 对幂次为偶数有优化。当为powi(3,5)时,是这样的3*(81),即把3^5=3*(3^4)
static inline double powi(double base, int times)
{
	double tmp = base, ret = 1.0;

	for(int t=times; t>0; t/=2)
	{
		if(t%2==1) ret*=tmp;
		tmp = tmp * tmp;
	}
	return ret;
}

以下几个是调试信息输出
static void print_string_stdout(const char *s)
{
	fputs(s,stdout);
	fflush(stdout);
}
static void (*svm_print_string) (const char *) = &print_string_stdout;

#if 1
static void info(const char *fmt,...)
{
	char buf[BUFSIZ];
	va_list ap;
	va_start(ap,fmt);
	vsprintf(buf,fmt,ap);
	va_end(ap);
	(*svm_print_string)(buf);
}
#else
static void info(const char *fmt,...) {}
#endif

函数指针专题

在libsvm中有如下代码:

static void print_string_stdout(const char *s)
{
	fputs(s,stdout);
	fflush(stdout);
}
static void (*svm_print_string) (const char *) = &print_string_stdout;
我在论坛中曾经发帖:

看了Pump天天学习同学的回复,我才回想起来:第六行那原来是个函数指针,平时没用到,就给忘了,只能拿出教材重新来学习一遍:

函数指针是指向函数而非指向对象的指针。像其他指针一样,函数指针也指向某个特定的类型。函数类型由其返回类型以及形参表确定,而与函数名无关:

// pf points to function returning bool thar takes two const string references
bool (*pf) (const string &, const string &);
这个语句将pf声明为指向函数的指针,它所指向的函数带有两个const string &类型的形参和bool类型的返回值。

注意*pf两侧的圆括号是必需的,若没有,则就不是函数指针了。

// declares a function named pf that returns a bool*
bool *pf (const string &, const string &)

typedef简化函数指针的定义

函数指针类型相当冗长。使用typedef为指针类型定义同义词,可将函数指针的使用大大简化

typedef bool (*cmpFn)(const string &, const string &)
该定义表示cmpFn是一种指向函数的指针类型的名字。该指针类型为:“指向返回bool类型并带有两个const string 引用形参的函数的指针”。在要使用这种函数指针类型时,只需直接使用cmpFn即可,不必每次都把整个函数类型声明全部写出来。


通过指针调用函数

指向函数的指针可用于调用它所指向的函数,可以不需要使用解引用操作符,直接通过指针调用函数:

bool lengthCmp(const string&, const string &);
cmpFn pf = lengthCmp;
lengthCmp=("hi","bye");//direct call
pf("hi","bye");//equivalent call: pf1 implicitly dereferenced
(*pf)("hi","bye");//equivalent call: pf1 explicitly dereferenced

Ref:《C++ Primer 4th》pp237-239

本文地址:http://blog.csdn.net/linj_m/article/details/19542421

微博:林建民-机器视觉


libsvm报错 make 错误使用 mex svm.obj:svm.cpp:(.text+0x10de): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x1114): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x11fb): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x1225): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x18f1): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x190b): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x1929): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x1964): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x19e7): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x1a09): more undefined references to `operator new[](unsigned long long)' follow svm.obj:svm.cpp:(.text+0x2161): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x216f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x217d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x218b): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2199): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x21a7): more undefined references to `operator delete[](void*)' follow svm.obj:svm.cpp:(.text+0x21f0): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2200): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x220c): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x224d): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x22e7): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x22f3): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x23f8): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x243d): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x24fe): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x250f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2520): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2528): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x258b): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2596): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x25a2): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2667): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x26b9): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x26d1): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2700): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x27d3): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2802): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x287f): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x2890): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x28a1): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x28b2): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x28c3): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x28d4): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2919): more undefined references to `operator delete[](void*)' follow svm.obj:svm.cpp:(.text+0x2961): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x296c): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2978): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2a63): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x2ab5): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2acd): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2afc): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2bd3): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2c02): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2c86): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x2c97): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2ca8): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2cb9): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2cca): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2cdb): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2d39): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2dfb): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2e64): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2e83): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x2ec8): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x2f82): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x2fa3): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x2fb4): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x3036): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x303f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x3067): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x3073): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x3118): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x3138): undefined reference to `operator new(unsigned long long)' svm.obj:svm.cpp:(.text+0x3182): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x3239): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x325a): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text+0x326b): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x32af): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x32b7): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x32d3): undefined reference to `operator new[](unsigned long long)' svm.obj:svm.cpp:(.text+0x32e1): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x32f9): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x3300): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x332e): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x3333): undefined reference to `__cxa_throw_bad_array_new_length' svm.obj:svm.cpp:(.text+0x3338): more undefined references to `__cxa_throw_bad_array_new_length' follow svm.obj:svm.cpp:(.text+0x1239): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text+0x1275): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.xdata+0x1dc): undefined reference to `__gxx_personality_seh0' svm.obj:svm.cpp:(.text$_ZN6SolverD0Ev[_ZN6SolverD0Ev]+0x6): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN9Solver_NUD0Ev[_ZN9Solver_NUD0Ev]+0x6): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD1Ev[_ZN5SVC_QD1Ev]+0x21): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD1Ev[_ZN5SVC_QD1Ev]+0x3f): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD1Ev[_ZN5SVC_QD1Ev]+0x4d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD1Ev[_ZN11ONE_CLASS_QD1Ev]+0x31): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD1Ev[_ZN11ONE_CLASS_QD1Ev]+0x3f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x31): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x3f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x4d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x5b): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x69): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD1Ev[_ZN5SVR_QD1Ev]+0x77): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD0Ev[_ZN11ONE_CLASS_QD0Ev]+0x31): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD0Ev[_ZN11ONE_CLASS_QD0Ev]+0x3f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN11ONE_CLASS_QD0Ev[_ZN11ONE_CLASS_QD0Ev]+0x5b): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD0Ev[_ZN5SVC_QD0Ev]+0x21): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD0Ev[_ZN5SVC_QD0Ev]+0x3f): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD0Ev[_ZN5SVC_QD0Ev]+0x4d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVC_QD0Ev[_ZN5SVC_QD0Ev]+0x69): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x31): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x3f): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x4d): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x5b): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x69): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x77): undefined reference to `operator delete[](void*)' svm.obj:svm.cpp:(.text$_ZN5SVR_QD0Ev[_ZN5SVR_QD0Ev]+0x93): undefined reference to `operator delete(void*, unsigned long long)' svm.obj:svm.cpp:(.rdata$_ZTI7QMatrix[_ZTI7QMatrix]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI6Kernel[_ZTI6Kernel]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI6Solver[_ZTI6Solver]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI9Solver_NU[_ZTI9Solver_NU]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI5SVC_Q[_ZTI5SVC_Q]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI11ONE_CLASS_Q[_ZTI11ONE_CLASS_Q]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTI5SVR_Q[_ZTI5SVR_Q]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info' svm.obj:svm.cpp:(.rdata$_ZTV6Kernel[_ZTV6Kernel]+0x10): undefined reference to `__cxa_pure_virtual' svm.obj:svm.cpp:(.rdata$_ZTV6Kernel[_ZTV6Kernel]+0x18): undefined reference to `__cxa_pure_virtual' collect2.exe: error: ld returned 1 exit status 出错 make (第 7 行) mex -O -largeArrayDims -I..\ svmtrain.c svm.obj svm_model_matlab.obj ^^^
最新发布
07-28
在使用 LibSVM 进行 `make` 编译时,如果出现 `mex` 错误,提示 `undefined reference to 'operator new[]'` 或 `operator delete[]` 等符号问题,这通常与 MEX 文件的编译环境配置或 C++ 标准库的链接有关。这类错误常见于 MATLAB 的 MEX 编译过程中,尤其是在使用较新版本的编译器或操作系统时。 此类问题的根源在于,默认情况下 MATLAB 的 `mex` 编译器可能未正确链接 C++ 标准库,导致找不到标准 C++ 操作符(如 `new` `delete`)的实现[^1]。此外,不同平台(如 Linux、macOS)的编译器版本标准库实现也可能引发此类链接错误。 ### 解决方法 #### 1. 显式链接标准 C++ 库 在调用 `make` 之前,可以修改 `Makefile` 中的 `MEX` 命令,显式添加对 C++ 标准库的链接。例如,在 `MEX` 编译命令中加入 `-lstdc++`: ```makefile MEX = mex -cxx -largeArrayDims -lstdc++ ``` 这样可以确保编译器在链接阶段包含标准 C++ 库,从而解决 `undefined reference` 的问题[^1]。 #### 2. 指定 C++ 标准版本 如果使用的是较新的编译器,可能还需要指定 C++ 标准版本,以确保兼容性。例如: ```makefile MEX = mex -cxx -largeArrayDims CXXFLAGS="\$CXXFLAGS -std=c++11" -lstdc++ ``` #### 3. 使用完整的 MEX 编译命令 手动编译单个 `.cpp` 文件进行测试,以确认是否为全局问题: ```bash mex -cxx -largeArrayDims -lstdc++ svm_train.cpp ../svm.cpp ``` #### 4. 更新 MATLAB 的编译器配置 在某些情况下,MATLAB 可能未正确识别系统中的 C++ 编译器。可以尝试运行: ```matlab mex -setup cpp ``` 确保 MATLAB 使用的是支持 C++11 或更高版本的编译器。 ### 示例修正后的 Makefile 片段 ```makefile MEX = mex -cxx -largeArrayDims -lstdc++ CXXFLAGS="\$CXXFLAGS -std=c++11" ``` ### 验证与调试建议 - 如果问题仍然存在,可尝试使用 `nm` 或 `objdump` 工具检查 `svm.cpp` 编译生成的 `.o` 文件是否包含 `operator new[]` `operator delete[]` 的调用。 - 确保 MATLAB 使用的编译器版本与系统默认编译器一致。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值