【问题标题】:C++ char array move null terminator properly?C ++ char数组正确移动空终止符?
【发布时间】:2012-03-06 18:59:25
【问题描述】:

您好,我的问题有点难以解释,所以我将在这里发布我的代码部分并用一个示例来解释问题。

这里的代码有一个大数组和一个小数组,其中大数组被分成小部分,存储在小数组中,小数组在屏幕上输出其内容。
然后我释放小数组的分配内存并用大数组的下一部分再次初始化它:

//this code is in a loop that runs until all of the big array has been copied
char* splitArray = new char[50];        
strncpy(splitArray, bigArray+startPoint, 50); //startPoint is calculated with every loop run, it marks the next point in the array for copying

//output of splitArray on the screen here

delete splitArray;
//repeat loop here

现在我的问题是输出的字符串每次都有一些随机符号。例如"some_characters_here...last_char_hereRANDOM_CHARS_HERE".

在深入研究之后,我发现 splitArray 实际上的大小不是 50,而是 64,空终止符为 64。 所以当我从 bigArray 复制到 splitArray 时,在真实字符串之后仍然有 14 个随机字符,当然我不想输出它们。

一个简单的解决方案是手动将 splitArray 中的空终止符设置为 [50],但随后程序无法再次删除该数组。

谁能帮我找到解决方案?最好有一些示例代码,谢谢。

【问题讨论】:

  • 应该是delete[],而不是delete。这几乎肯定会导致与内存相关的问题。
  • 一件事:delete splitArray; 应该是delete[] splitArray;
  • 哇这么短的时间里有这么多答案,我什至不知道该回答哪一个,但非常感谢大家;)在C++中使用字符串更好吗?因为我需要一个 char* 来输出数组。为什么在我这样初始化数组时使用 delete[] 更好?一些解释的链接就足够了,但如果你愿意,你也可以在这里解释

标签: c++ arrays null char terminator


【解决方案1】:

如果只是设置splitArray[49] = 0,程序如何“再次删除数组失败”?不要忘记,长度为 50 的数组的索引范围是 0 到 49。splitArray[50] = 0 正在写入分配给splitArray 的内存之外的内存,这会带来所有后果。

【讨论】:

  • 虽然 C++ 接受它,但我发现将 0'\0' 混合使用会产生误导。它们在概念上是根本不同的东西。
  • 这是一个错误,我用 [50] 初始化了数组,但也将空终止符写入 [50] 而不是 [49] 应该是。所以在增加数组大小 +1 并将空终止符写入 [50] 之后它工作得很好,谢谢
【解决方案2】:

当您为splitArray分配内存时,内存中没有填充NULL字符,您需要明确地这样做。因此,您的字符串未正确以 NULL 结尾。为此,您可以在分配时使用 NULL 字符进行 char* splitArray = new char[51](); 初始化(请注意,我分配了 51 个字符以在末尾添加额外的 NULL 字符)。 .另请注意,您需要使用delete[] splitArray; 而不是delete splitArray;

【讨论】:

    【解决方案3】:

    这样做就足够了:

    char* splitArray = new char[50 + 1];        
    strncpy(splitArray, bigArray+startPoint, 50);
    splitArray[50] = '\0';
    

    我真的很怀疑你为什么要这样做。这更干净:

    std::string split(bigArray+startPoint, 50);
    

    它仍然会进行复制,但会为您处理(取消)分配和终止。您可以像这样获取底层字符指针:

    char const *s = split.c_str();
    

    它将正确地以 nul 结尾,并且与字符串对象具有相同的生命周期(即,您不需要 freedelete 它)。


    注意。我没有更改您的原始代码,但丢失神奇的整数文字也是一个好主意。

    【讨论】:

    • 到目前为止,我在 c++ 中对字符串的工作并不多。我需要传递一个 char* 来输出内容,我假设从字符串到 char* 也可以进行对话?
    • 如果您仍然在使用 C++,那么值得找出标准库中免费提供的工具,而不是重新发明一切。
    【解决方案4】:

    函数strncpy 的缺点是,如果源字符串包含超过 50 个字符,它不会终止目标字符串。好像你的情况一样!

    如果这真的是 C++,你可以用 std::string splitArray(bigArray+startPoint, 50) 来做。

    【讨论】:

      【解决方案5】:

      我发现您的代码存在一些问题:

      1. 如果你使用new []分配,你需要使用delete []释放(不是delete
      2. 你为什么还要使用freestore?据我所知,您不妨使用本地数组。
      3. 如果要在数组中存储 50 个字符,则需要 51 个作为终止空字符。

      你想要一些代码:

      while(/* condition */)
      {
          // your logic
      
          char splitArray[51];
          strncpy(splitArray, bigArray+startPoint, 50);
          splitArray[50] = '\0';
      
          // do stuff with splitArray
          // no delete
      }
      

      【讨论】:

      • 笨蛋,我忘记了数组的从零开始的索引。所以我设置了 splitArray[50],但也用 splitArray[50] 而不是 [50+1] 初始化了 splitArray。这只是我的一些示例代码,我没有用常量值初始化数组。据我所知,delete[] 与 delete 具有相同的效果,但我已经听说我应该将它用于此类代码。你能解释一下为什么吗?
      • @user1175111:看到这个问题:stackoverflow.com/questions/2425728/…
      • 或者这可能是编译器自动处理的?因为在调试器中,当我使用 delete[] 或 delete 时,我真的看不到任何区别,并且到目前为止从未遇到过 delete 和数组的问题。我正在使用 Visual Studio 2010 顺便说一句。
      • 它可能在调试版本中被正确处理,但在发布版本中却没有。它可能会泄漏内存。它可能会做一些其他更糟糕的事情。我不知道在 VC++10 上这种情况会发生什么,但即使现在一切正常,但当你更改一些无害的编译器设置或一些完全不相关的条件突然不同时,它可能会回来咬你。只是不要这样做。 delete [] 的存在是有原因的。
      猜你喜欢
      • 1970-01-01
      • 2012-04-20
      • 1970-01-01
      • 1970-01-01
      • 2012-10-07
      • 2014-04-08
      • 1970-01-01
      • 1970-01-01
      • 2013-10-22
      相关资源
      最近更新 更多