0

我正在构建快速的“配置阅读器”,它从文件中读取设置。问题是,该函数返回“800”字符串,而带有该输入的 atol 返回 0。我不确定我做错了什么。

所以,大致是这样的:

char *txtval=GetParamFromLine("WINDOW_WIDTH");
val = atol(txtval); 

char* GetParamFromLine(char*parameter)
{
   char text[16];
   //
   // do the reading procedure and fill the text
   //
   return text;
}

结果: atol(text) = 0 (其中 text = "800" )

谢谢你的帮助!

4

4 回答 4

4

您需要将“文本”存储在堆而不是堆栈上。否则,当函数结束时,变量会超出范围,并且您将尝试访问该内存段时出现未定义的行为。您可以在堆上分配内存,然后在完成后释放它,

char *txtval=GetParamFromLine("WINDOW_WIDTH");
val = atol(txtval); 
free txtval;

// Caller is responsible for freeing returned buffer
char* GetParamFromLine(char*parameter)
{
   char text* = malloc(sizeof(char)*16);
   //
   // do the reading procedure and fill the text
   //
   return text;
}

或者传递一个指向应该存储结果的缓冲区的指针。

char txtval[16];
GetParamFromLine("WINDOW_WIDTH", txtval);
val = atol(txtval); 

void GetParamFromLine(char *parameter, char *resultBuffer)
{
   //
   // do the reading procedure and fill the text into resultBuffer
   //
}
于 2013-09-05T20:54:58.127 回答
3

您正在返回一个指向本地范围变量的指针。函数调用后内存text超出范围,因此指向它的指针没有意义,因为内存将被回收......

您需要为 分配一些长期存储空间text,或者将GetParamFromLine和组合atol到同一个函数中。

于 2013-09-05T20:53:38.903 回答
2

使文本静态:

char* GetParamFromLine(char*parameter)
{
    static char text[16];
    ... do something
    return text;
}

您的版本正在使用堆栈驻留版本,在使用之前可能会被覆盖。静态存储类说明符确保

返回的缓冲区只会在下一次调用 GetParameterFromLine 之前有效。

一般来说,调用者最好将缓冲区和缓冲区大小作为参数提供给这样的函数。

char *GetParamFromLine(const char *parameter, char *text, size_t text_size)
{
    ... do something
    return text;
}

“做某事”代码应仔细观察该大小。您必须决定是否截断参数、返回一个空字符串、返回一个 NULL 指针,或者如果实际数据比缓冲区长的话。

于 2013-09-05T20:52:47.167 回答
2

该问题是由返回指向局部变量的指针引起的。当函数GetParamFromLine返回时,变量text超出范围。返回的指针不再有效,导致未定义的行为。您必须以其他方式返回数据,例如:

std::string txtval=GetParamFromLine("WINDOW_WIDTH");
val = atol(txtval.c_str());

std::string GetParamFromLine(char*parameter)
{
   char text[16];
   //
   // do the reading procedure and fill the text
   //
   return std::string(text);
}

将返回类型从指向局部变量的指针更改为std::string缓解返回指向局部变量的指针的问题。使用的资源由std::string​​对象管理并自动清理。

作为替代方案,您也可以删除atol呼叫并使用 astd::istringstream代替。一个好处是这样可以更好地报告错误:

std::string txtval=GetParamFromLine("WINDOW_WIDTH");
std::istringstream iss(txtval);
int val( 0 );
iss >> val;

现在,如果您真的想更进一步,您可以将字符串的检索和转换为整数数据类型结合起来,并参数化这个新函数模板的返回类型:

template<typename T>
T GetValueFromLine(const std::string& param) {
    std::string txtval=GetParamFromLine(param.c_str);
    std::istringstream iss(txtval);
    T val = T();
    iss >> val;
    return val;
}

使用此模板,您可以执行以下操作:

long wndWidth = GetValueFromLine<long>("WINDOW_WIDTH");
bool showInfo = GetValueFromLine<bool>("SHOW_INFO");
....

注意:省略了错误处理。

于 2013-09-05T21:02:53.867 回答