我有一个计算几个不同值的函数:
int ASPfile::get_dimensions(int* Lat, int* Lon,
vector<double>* Latgrid, vector<double>* Longrid) {
_latsize = get_latsize();
_lonsize = get_lonsize();
Lat = &_latsize;
Lon = &_lonsize;
latgrid = read_latgrid();
longrid = read_longrid();
*Latgrid = latgrid;
*Longrid = longrid;
return 0;
}
此函数调用如下:
int* Latsize = NULL;
int* Lonsize = NULL;
vector<double>* Latgrid = NULL;
vector<double>* Longrid = NULL;
int res = asp->get_dimensions(Latsize,Lonsize,Latgrid,Longrid);
然后,我尝试按如下方式访问值:
cout << (*Szagrid)[4];
或者像这样
cout << Szagrid->at(4);
该程序编译时没有任何警告。但是,当我尝试访问get_dimensions()应该“填充”的指针时, valgrind告诉我以下内容:
==10531== Invalid read of size 8
==10531== at 0x633D5DA: std::vector<double, std::allocator<double> >::operator=(std::vector<double, std::allocator<double> > const&) (in /home/myhome/src/libiup/Release/libiup.so)
==10531== by 0x633CADC: ASPfile::get_dimensions(int*, int*, int*, std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*) (in /home/myhome/src/libiup/Release/libiup.so)
==10531== by 0x41B90B: ASPfileTest::test_get_dimensions() (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41BACC: ASPfileTest::operator()() (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41E229: boost::function0<void>::operator()() const (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41E7C2: cute::runner<cute::eclipse_listener>::runit(cute::test const&) (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41D26A: runSuite() (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41DBC4: main (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==10531==
==10531== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==10531== Access not within mapped region at address 0x0
==10531== at 0x633D5DA: std::vector<double, std::allocator<double> >::operator=(std::vector<double, std::allocator<double> > const&) (in /home/myhome/src/libiup/Release/libiup.so)
==10531== by 0x633CADC: ASPfile::get_dimensions(int*, int*, int*, std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*) (in /home/myhome/src/libiup/Release/libiup.so)
==10531== by 0x41B90B: ASPfileTest::test_get_dimensions() (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41BACC: ASPfileTest::operator()() (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41E229: boost::function0<void>::operator()() const (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41E7C2: cute::runner<cute::eclipse_listener>::runit(cute::test const&) (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41D26A: runSuite() (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== by 0x41DBC4: main (in /home/myhome/src/libiup_test/Release/libiup_test)
==10531== If you believe this happened as a result of a stack overflow in your
==10531== program's main thread (unlikely but possible), you can try to increase
==10531== the size of the main thread stack using the --main-stacksize= flag.
==10531== The main thread stack size used in this run was 8388608.
我不太明白我做错了什么;可能是显而易见的事情,但我似乎无法找到问题。
非常感谢任何帮助!
答案 0 :(得分:5)
你在get_dimensions中写入内存,但你实际上并没有真正分配内存。相反,您只是传递NULL指针。
一个可能的解决方法是将您的主叫代码更改为:
int Latsize, Lonsize;
vector<double> Latgrid;
vector<double> Longrid;
int res = asp->get_dimensions(&Latsize,&Lonsize,&Latgrid,&Longrid);
这会自动在堆栈上为变量分配空间,然后将分配的空间的地址传递给get_dimensions,这将修改值。
答案 1 :(得分:5)
你的问题得到了其他人的好评,但是我想指出,既然这是C ++,而不是C,如果你只是使用引用而不是指针,那么所有这些混乱都可以避免。这通常是你应该在这种情况下做的事情(如果不需要NULL返回值)
int ASPfile::get_dimensions(int& Lat, int& Lon,
vector<double>& Latgrid, vector<double>& Longrid) {
Lat = get_latsize();
Lon = get_lonsize();
Latgrid = read_latgrid();
Longrid = read_longrid();
return 0;
}
// Call like this
int Latsize;
int Lonsize;
vector<double> Latgrid;
vector<double> Longrid;
int res = asp->get_dimensions(Latsize,Lonsize,Latgrid,Longrid);
答案 2 :(得分:3)
函数的签名指向我的信号我可能也会传递NULL
指针,如果我手头没有适合的对象或者我对特定结果不感兴趣。但是,您的函数不会检查此函数并愉快地写入地址0
。
如果必须将正确的对象传递给函数,那么为什么不使用引用而不是指针?它们旨在用于您想要做的事情,更容易理解,更难以出错。
int ASPfile::get_dimensions( int& Lat
, int& Lon
, vector<double>& Latgrid
, vector<double>& Longrid );
答案 3 :(得分:1)
“latgrid
”和“longrid
”定义在哪里?如果它们是ASPFile :: get_dimensions的本地,那么它们的析构函数将在函数返回时被调用,从而销毁它们。
答案 4 :(得分:0)
同意所有关于指针的说法。作为一个经验法则 - 除非你真的需要,否则不要使用它们。 与此同时,这里使用的模式看起来凌乱而丑陋,并且对get_dimensions函数的需求是完全模糊的。你正在增加不必要的复杂程度。
而不是这个,我怀疑你在ASPFile上的原型函数public中使用的那些get_和read_函数就足够了:
int Latsize = asp->get_latsize();
int Lonsize = asp->get_lonsize();
vector<double> Latgrid = asp->read_latgrid();
vector<double> Longrid = asp->read_longrid();
保持简单。