在调用memset()时,我的一些代码中出现了一些奇怪的,间歇性的数据中止(<5%的时间memset() 问题是,除非代码运行了几天,否则通常不会发生,因此很难在行为中捕获它。

我正在使用以下代码:

char *msg = (char*)malloc(sizeof(char)*2048);
char *temp = (char*)malloc(sizeof(char)*1024);
memset(msg, 0, 2048);
memset(temp, 0, 1024);
char *tempstr = (char*)malloc(sizeof(char)*128);

sprintf(temp, "%s %s/%s %s%s", EZMPPOST, EZMPTAG, EZMPVER, TYPETXT, EOL);
strcat(msg, temp);

//Add Data
memset(tempstr, '\0', 128);
wcstombs(tempstr, gdevID, wcslen(gdevID));
sprintf(temp, "%s: %s%s", "DeviceID", tempstr, EOL);
strcat(msg, temp);

正如你所看到的,我并没有尝试使用尺寸大于最初使用malloc()分配的memset

有人看到这可能有什么问题吗?

===============>>#1 票数:21 已采纳

如果没有可用内存, malloc可以返回NULL 你没有检查。

===============>>#2 票数:4

有几件事情。 你正在使用本质上不安全的sprintf ; 除非你100%肯定你不会超过缓冲区的大小,你几乎总是喜欢snprintf 这同样适用于strcat ; 更喜欢更安全的替代strncat

显然,这可能不是解决什么,但它会帮助现货否则什么可能是很烦人的斑点错误很长的路要走。

===============>>#3 票数:3

如果没有可用内存,malloc可以返回NULL。 你没有检查。

对,你是......我没有想到这一点,因为我正在监视记忆,而且有足够的免费。 有没有办法在系统上有可用内存,但malloc失败?

是的,如果内存碎片化。 此外,当您说“监视内存”时,系统上可能会有某些内容偶尔消耗大量内存,然后在您发现之前将其释放。 如果您对malloc的调用发生,则不会有任何可用内存。 - 乔尔

无论哪种方式......我会添加那个检查:)

===============>>#4 票数:1

wcstombs没有得到目标的大小,所以理论上它可以缓冲溢出。

为什么你使用sprintf我认为是常量? 只需使用:

EZMPPOST" " EZMPTAG "/" EZMPVER " " TYPETXT EOL

C和C ++将字符串文字声明组合成一个字符串。

===============>>#5 票数:0

它可能是你的处理器。 某些CPU无法处理单个字节,并且要求您使用单词或块大小,或者具有只能用于字或块对齐数据的指令。

通常编译器会知道这些并解决它们,但有时你可以将一个区域作为字节malloc,然后尝试将其作为一个结构或宽于一个字节的字段来解决,编译器将无法捕获它,但处理器稍后会抛出数据异常。

除非你使用不寻常的CPU,否则不会发生这种情况。 例如,ARM9会这样做,但i686不会。 我看到它被标记为windows mobile,所以也许你有这个CPU问题。

===============>>#6 票数:0

您应该使用calloc来清除新分配的内存,而不是使用malloc后跟memset 除此之外,做Joel所说的。

===============>>#7 票数:0

NB从其他答案中借鉴了一些评论并整合到一起。 代码全是我的......

  • 检查您的错误代码。 例如,如果没有可用的内存,malloc可以返回NULL。 这可能导致您的数据中止。
  • 根据定义,sizeof(char)为1
  • 使用snprintf而不是sprintf来避免缓冲区溢出
    • 如果EZMPPOST等是常量,那么你不需要格式字符串,你可以将几个字符串文字组合为STRING1“”STRING2“”STRING3和strcat整个批次。
  • 您使用的内存比您需要的多得多。
  • 只需进行一次小改动,您就不需要首先调用memset。 这里没有什么需要零初始化。

此代码执行相同的操作,安全,运行速度更快,并且使用更少的内存。

    // sizeof(char) is 1 by definition. This memory does not require zero
    // initialisation. If it did, I'd use calloc.
    const int max_msg = 2048;
    char *msg     = (char*)malloc(max_msg);
    if(!msg)
    {
       // Allocaton failure
       return;
    }
    // Use snprintf instead of sprintf to avoid buffer overruns
    // we write directly to msg, instead of using a temporary buffer and then calling
    // strcat. This saves CPU time, saves the temporary buffer, and removes the need
    // to zero initialise msg.
    snprintf(msg, max_msg, "%s %s/%s %s%s", EZMPPOST, EZMPTAG, EZMPVER, TYPETXT, EOL);

   //Add Data
   size_t len = wcslen(gdevID);
   // No need to zero init this
   char* temp = (char*)malloc(len);
   if(!temp)
   {
      free(msg);
      return;
   }
   wcstombs(temp, gdevID, len);
   // No need to use a temporary buffer - just append directly to the msg, protecting 
   // against buffer overruns.
   snprintf(msg + strlen(msg), 
           max_msg - strlen(msg), "%s: %s%s", "DeviceID", temp, EOL);
   free(temp);

===============>>#8 票数:0

你尝试过使用Valgrind吗? 这通常是调试这些错误的最快速,最简单的方法。 如果您正在读取或写入超出已分配内存的范围,它将为您标记它。

===============>>#9 票数:0

你正在使用本质上不安全的sprintf; 除非你100%肯定你不会超过缓冲区的大小,你几乎总是喜欢snprintf。 这同样适用于strcat; 更喜欢更安全的替代strncat。

是的.....我最近主要做.NET,老习惯很难。 我可能从我之前写的其他东西中删除了那段代码......

但我会尽量不要在将来使用它们;)

===============>>#10 票数:0

你知道它甚至可能不是你的代码......是否有任何其他程序运行可能会有内存泄漏?

  ask by Adam Haile translate from so

未解决问题?本站智能推荐: