在调用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

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

1回复

可以通过编译器删除`memset`函数调用吗?

我在这里读到,如果编译器知道传递的内存缓冲区从未再次使用过 ,那么编译器可以自由地删除对memset调用。 怎么可能? 在我看来(从核心语言的角度来看) memset只是一个常规函数,编译器无权假设其中发生的任何事情都没有副作用。 在链接文章中,他们展示了Visual C ++ 10如
12回复

使用现代编译器在C ++中使用“memset”功能的状态

语境: 不久之前,我偶然发现了Alexandrescu的2001年DDJ文章: http : //www.ddj.com/cpp/184403799 它是关于比较各种方法来初始化缓冲区到某个值。 就像“memset”对单字节值的作用一样。 他比较了各种实现(memcpy,显式“f
1回复

在将memset设置为默认值后验证数组中的更改

我有以下代码,其中:(1)使用默认值初始化数组; (2)对数组做点事; (3)检查数组是否仍然是默认的。 我不确定(3)。 我将检查数组是否仅为默认值的方式如下(即,这就是我编写check_array_is_default()函数的方式):
2回复

功能是否导致巨大的内存泄漏?

我有以下功能: 我已将问题缩小到至少两行: 每次我反复调用它时,内存都会猛增,直到崩溃。 我这样使用它: 我真的不知道这怎么可能引起任何问题。 为了测试,我将其更改为: 当我这样做时,它绝对没有问题。 我看不出算术如何导致内存使用率猛增。 谢谢
2回复

OpenCL内核重新编译的问题减慢了程序的速度,并因此导致了可能的内存问题

我是OpenCL的新手,正在运行Nvidia 330图形卡的OS X 10.6。 我正在用C ++进行布料模拟,已经设法编写了一个用于编译和运行的内核。 问题是它的运行速度比不使用OpenCL的cpu慢。 我相信这样做的原因是,每次我调用update()方法进行一些计算时,我都会设置上下文
2回复

在C ++中的指针数组中,内存过量使用会导致指针存储在非连续的内存块中吗?

我在XCode中编写一些代码,并且在部分填充数组时注意到一些有趣的事情。 我的代码基本上是这样的(为简单起见,这只是一个示例): 这个代码片段最终打印出了以下内容: 我期望这样: 之后,我阅读下面有关操作系统如何过量使用内存的文章: 指针数组的C ++内存分配 操
1回复

重新存储已经存储在目标变量中的一个值是否会导致重写并延长运行时间? [重复]

这个问题已经在这里有了答案 : “假设”规则到底是什么? (3个答案) 2小时前关闭。 我真正担心的是,如果我编写了一个导致将
3回复

加快创建和读取数据的速度

关于在C / C ++中创建和读取数据的速度,我有一些小问题: =>如果我需要在任何类型的数组中填充数据(想像一个2048 * 2048数组),使用循环并填充每个单元格更快,然后从文件加载它? (不包括打开和关闭文件所花费的时间)。 =>如果数据在单独的文件中并可以读取
3回复

为什么要支持数据结构对齐?

结构的每个成员的类型通常具有默认对齐方式,即,每个结构成员都在预定边界上对齐。 因此,在以下Wiki示例中执行填充: 应保持对齐的(实际)原因是什么?
2回复

为动态数据结构预分配内存

我有一个问题/好奇心。 假设我想实现一个列表,例如我基本上可以使用cormen book方法。 在哪里解释如何实现,插入,删除,键搜索等。 然而,对于内存使用而言,没有任何说法。 例如,如果我想在整数列表中插入一个整数。 我可以例如首先创建一个节点(我在那里分配内存)插入整数然后在