为什么memset没有按预期工作?

时间:2017-09-01 00:52:40

标签: c windows visual-studio

我有以下程序:(功能:填充字符串右侧的空格,在这里使用astreix以方便视觉):

os:windows(visual studio)

#include "stdafx.h"
#include<stdlib.h>
#include<string.h>

#define CBUFFSIZE 48

void right_pad_str(char *pad_str, char *buff,int max_buffsize){

   int padstr_len = 0;
   int space_len = 0;
   char *end_str = NULL;

   memset(buff, '\0', max_buffsize);
   padstr_len = strlen(pad_str);
   space_len = ((max_buffsize - 1) - padstr_len);

   strncpy_s(buff, max_buffsize, pad_str, strlen(pad_str));

   end_str = buff +padstr_len;

   memset((end_str), '*', space_len);

   buff[max_buffsize] = '\0';

}

int _tmain(int argc, _TCHAR* argv[]){
    char tmpstr[49] = { '\0' };
    char *str = "hello_world";

    right_pad_str(str, tmpstr, CBUFFSIZE + 1);

    return 0;
 }

当我查看memeset的值时,memset上似乎存在一个问题,它看起来非常不正确,即垃圾为什么会这样?最后我null终止字符串但我看到垃圾值和堆栈损坏错误,而不是确定我的逻辑有什么问题。

(我附上了相同的快照)

memset invalid value

2 个答案:

答案 0 :(得分:3)

在这个更简单的例子中可以看到意外的行为:

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

int main(int argc, char **argv)
{
    char buffer[3];
    buffer[0] = '\0';
    buffer[1] = '\0';
    buffer[2] = '\0';
    strncpy_s(buffer, 3, "*", 1);
    printf("%u\n", (unsigned int)(unsigned char)buffer[2]);
    return 0;
}

输出为254而不是0,但仅在调试版本中。这种情况发生在调用strncpy_s期间,这意外地在副本结束时写入目标缓冲区,可能是为了暴露代码中的错误(已经指出过)。

NB:退休忍者非常正确地指出(在问题的评论中)这个描述略微不准确,在the documentation's细则中,我原先忽略了这一点:

  

这些函数的调试版本首先使用0xFD填充缓冲区。要禁用此行为,请使用_CrtSetDebugFillThreshold。

(事实上,至少在Visual Studio 2010中,它用0xFE填充缓冲区。)

答案 1 :(得分:2)

@Harry Johnston很好的答案解释了出了什么问题。

要将字符串填充到其数组大小,建议:

1)随着'\0'memset(buff, ...);... strncpy_s(buff,...)的过度写作而随后写入数据。

2)使用size_t索引数组和 string 数学。 size_t是作业的正确大小整数。

3)注意糟糕的表单调用,比如使用长度超过目标的pad或者调用大小为0的调用。也可以检查NULL指针。

void right_pad_str(const char *pad_str, char *buff, size_t buff_size){ 
  if (buff_size > 0) {
    size_t pad_size = strlen(pad_str) + 1;
    if (pad_size > buff_size) {
      pad_size = buff_size;
    }

    memcpy(buff, pad_str, pad_size - 1); 
    memset(&buff[pad_size - 1], '*', buff_size - pad_size);
    buff[buff_size - 1] = '\0';
  }
}

// usage
right_pad_str(str, tmpstr, sizeof tmpstr);