【问题标题】:Variable data corruption with C GCC on Fedora 17 64 bitFedora 17 64 位上的 C GCC 变量数据损坏
【发布时间】:2015-09-16 08:38:34
【问题描述】:

我正在创建一个临时缓冲区并使用 sprintf 将字符串复制到缓冲区。然后我调用函数analyzeRecordForPGDBOperation 传递缓冲区作为参数。我使用 strtok 解析字符串 |作为分隔符。我看到一个奇怪的问题,即使在 switch case 2 中正确打印了 codesite 的值,它的值后来也损坏了。当我在 case 3 和 case 4 中打印时,codesite 的值不正确。

我试图在 gdb 中使用监视代码站点变量来查看它的共振,我得到以下输出,但我不确定为什么会出现这个问题。

[root@pe1800xs64 主干]# uname -r 3.9.10-100.fc17.x86_64

“来自 GDB 的输出:”

旧值 = "71663138", '\000' 新值 = "\000\061\066\066\063\061\063\070", '\000'

/lib64/libc.so.6 中的 __strcpy_sse2_unaligned () 中的 0x00000038f30939ee

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main() 
{
    char tmp[256];
    sprintf(tmp, "%s", "99|71663138|316DEA40C62D6BA40B3C0AA2FE06C457|1442319758");
    analyzeRecordForPGDBOperation(tmp);
    return 0;
}

void analyzeRecordForPGDBOperation(char *data)
{
    char tempBuff[256] = {'\0',};
    char park[16] = {'\0',};
    char codesite[16] = {'\0',};
    char key[24] = {'\0',};
    char timestamp[16] = {'\0',};
    int caseVal = 0;
    sprintf(tempBuff, "%s", data);
    char *p = strtok(tempBuff,"|");

    for (; p != NULL; p = strtok(NULL, "|"))
    {
        caseVal++;
        switch(caseVal)
        {
            case 1:
                sprintf(park, "%s", p);
                break;
            case 2:
                sprintf(codesite, "%s", p);
                //Value of codesite is printed correctly here
                printf("\nCodesite: %s\n", codesite);
                break;
            case 3:
                sprintf(key, "%s", p);
                //Value of codesite is corrupted
                printf("\nCodesite Case 3: %s\n", codesite);
                break;
            case 4:
                sprintf(timestamp, "%s", p);
                //Value of codesite is corrupted
                printf("\nCodesite case 4: %s\n", codesite);
                break;
            default:
                break;
       }
    }
}

输出:

[root@pe1800xs64 主干]# ./a.out

analyzeRecordForPGDBOperation

代码站点:71663138

代码站点案例 3:

代码站点案例 4:

【问题讨论】:

  • 您正在将 32 个字母的密钥读入 24 字节的缓冲区。哎哟。
  • 尝试增加目标缓冲区的长度
  • 从不使用sprintf,但始终使用snprintf,例如snprintf(timestamp, sizeof(timestamp), "%s", p);;也可以考虑asprintf
  • 尽量不要以root用户运行程序

标签: c gcc gdb memory-alignment memory-corruption


【解决方案1】:

如果这个"316DEA40C62D6BA40B3C0AA2FE06C457" 是您需要复制到case 3 上的值,那么目标缓冲区key 不够大。

这会触发未定义的行为,这就是为什么即使您没有直接修改它,之后您也会在 codesite 中看到奇怪的结果。

【讨论】:

    【解决方案2】:

    我分配的缓冲区大小较小。缓冲区大小为 24,而我试图将 33 个字符复制到其中。因此,内存已损坏。 有了新尺寸,问题就迎刃而解了。

    字符码位[16] = {'\0',}; 字符键[35] = {'\0',};

    感谢您的帮助

    【讨论】:

      猜你喜欢
      • 2020-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多