【问题标题】:encountering exception when copying string using strncpy [closed]使用 strncpy 复制字符串时遇到异常 [关闭]
【发布时间】:2016-05-10 12:13:06
【问题描述】:

我有一个字符串,我正在迭代寻找一个特定的单词,它恰好在两个空格之间。

例如:

// where the word that I'm looking for is /docs/index.html
const char* c = "GET /docs/index.html HTTP/1.1\r\n";

我找到这个词如下;

const char* wbeg = strchr(c, ' ') + 1; // points to '/'
const char* wend = strchr(wbeg, ' ') -1; // points to 'l'

如果我想将该单词存储到另一个位置,我使用 strncpy 实现了这一点

char word[256];
strncpy(word, wbeg, wend - wbeg);

我收到以下错误

在 0x00007FFAAE8C4A74 (ucrtbased.dll) 处引发异常 ConsoleApplication1.exe: 0xC0000005: 访问冲突写入位置 0x0000000000000000.

【问题讨论】:

  • 您检查strchr() 的返回是否为NULL
  • char word[256]; --> char word[256]="";, strncpy(word, wbeg, wend - wbeg); --> strncpy(word, wbeg, wend - wbeg + 1);
  • @stanna:如果代码在函数之前中断,为什么不发布相关代码?
  • 是时候学习如何使用调试器了。
  • 提供的代码没有错误。当然,word after strncpy() 的某些使用会失败并导致“访问冲突写入位置 0x0000000000000000”。投票结束,因为这篇文章缺少“重现所需的最短代码”

标签: c pointers exception strncpy


【解决方案1】:

当您在帖子中展示的要点在一个简单的main() 程序中运行时,...

int main()
{
    const char* c = "GET /docs/index.html HTTP/1.1\r\n";
    const char* wbeg = strchr(c, ' ') + 1; // points to '/'
    const char* wend = strchr(wbeg, ' ') -1; // points to 'l'
    char word[256];
    strncpy(word, wbeg, wend - wbeg);

    printf("%s", word);

    return 0;
}

...在我的环境中没有观察到故障。因此,除了发布其余相关代码之外,唯一的建议都是围绕确保您没有调用 UB

1) 在您的声明中:

strncpy(word, wbeg, wend - wbeg);

`wend - wbeg` is == 15

/docs/index.html 的长度为 16 个字符。
将您的声明更改为:

strncpy(word, wbeg, (wend - wbeg)+1);

2) 从初始化变量开始:

  char word[SIZE] = ""  

3) strncpy 不会 NULL 终止。如果您要复制到的目标在使用前尚未初始化,或者您在使用后没有明确地为 null 终止,则可能会发生 UB。 示例:

char target[];  //contents of target are not guaranteed
char source[]="abcdefghijklmnopqrstuv";
strncpy(target, source, 3);

有可能得到以下结果:

|a|b|c|?|?|?|?|?|?|?|?|?|?|?|?|?|...

在哪里?可以是任何东西。

如果要保证 ASCII NUL 字节位于复制字节的末尾,可以使用以下内容:

strncpy (target, source, 3);
target[3] = 0;
|a|b|c|\0|?|?|?|?|?|?|?|?|?|?|?|?|...

4) 如果复制发生在两个重叠的对象之间,则行为未定义。确保在使用strncpy() 中的结果之前检查strchr() 函数的结果

【讨论】:

    【解决方案2】:

    strncpy 是一个糟糕的函数。如果 source 比 count 参数长,它不会正确终止字符串:

    char s[] = "AAAAA";
    strncpy(s, "BB", 2);
    // s is now "BBAAA", not "BB"
    

    您需要在复制后显式终止字符串。

    char word[SIZE];
    ptrdiff_t count = wend - wbeg + 1;
    if(count < SIZE) {
        memcpy(word, wbeg, count); // might as well use memcpy
        word[count] = '\0';
    }
    else // handle error
    

    【讨论】:

    • 他说他在调用 strncpy 时遇到错误。他没有显示他是否以零结束,所以你只是在猜测。 strncpy 也不是“糟糕的”;它就像指定的那样。
    • @PaulOgilvie strncpy 可能会按照指定的方式进行操作,并且对于它的用途可能很方便。但它的名字好不好?是否适合通用用途?它应该包含在标准库中吗?答案是否、否和
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多