【问题标题】:Strange behaviour of gcc in DebianDebian 中 gcc 的奇怪行为
【发布时间】:2014-06-06 02:51:42
【问题描述】:
char * stft (const char *fmt, ...) {

    va_list items;
    char *out;
    int magic = 0; // <-- here magic?

    va_start (items, fmt);
    vsprintf (out, fmt, items);
    va_end (items);

    return out;

}

像这样使用:

char *str = stft ("%s-%s %s", a, b, c);

这是有效的解决方案吗? 如果删除未使用的“魔术”变量-返回字符串后出现分段错误。 做错了什么?

$ gcc --version gcc (Debian 4.4.5-8) 4.4.5

$ unname -a Linux deep-station (squeeze) 2.6.32-5-686 #1 SMP Fri May 10 08:33:48 UTC 2013 i686 GNU/Linux

【问题讨论】:

  • 与问题无关,但不应该有初始化out的东西吗?
  • @guest:与问题无关——问题恰恰是out没有初始化,所以会发生崩溃。
  • 不错的侦探。谢谢

标签: c linux gcc debian


【解决方案1】:

您正在尝试写入未初始化的指针out。这就是你崩溃的原因。这是严重未定义的行为。神奇是巧合;它不会更好地定义行为。

最好使用vsnprintf():

char *out = malloc(256);
...
vsnprintf(out, 256, fmt, items);
...
return out;

或类似的东西。

您可以改进这一点。例如:

char *stft(const char *fmt, ...)
{
    va_list items;

    va_start(items, fmt);
    int length = vsnprintf(0, 0, fmt, items);
    va_end(items);
    char *out = malloc(length+1);
    if (out != 0)
    {
        va_start(items, fmt);
        vsnprintf(out, length+1, fmt, items);
        va_end(items);
    }

    return out;
}

确保在调用代码中释放分配的内存。

【讨论】:

  • >>> 确保释放调用代码中分配的内存。对于未使用的 free() 我想要解决方案并发现奇怪的行为
  • 对不起,我不明白你的评论。如果您不希望该函数分配内存,那么您有两种选择。更好的选择是传入一个缓冲区 (char *buffer) 及其长度 (size_t buflen),然后使用这些:vsnprintf(buffer, buflen, fmt, items)。更糟糕的选择是函数中的static char buffer[256];vsnprintf(buffer, sizeof(buffer), fmt, items);。这存在并发问题,这意味着您不能两次调用该函数并保留两个格式化字符串而无需显式复制。这两个可能都有一个太短的缓冲区。
  • 感谢您的解决方案!现在,我仅将全局缓冲区用于单次调用 stft() 并使用一次调用为当前 stft() 上下文重新分配缓冲区长度。非常感谢!
猜你喜欢
  • 2011-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-18
  • 1970-01-01
相关资源
最近更新 更多