2017-09-01 112 views
0

我有以下程序:(功能:墊空格串的右側,使用astreix這裏直觀方便):爲什麼memset不按預期工作?

操作系統:Windows(視覺工作室)

#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; 
} 

好像有memset中的一個問題,當我看着memeset後的值,它看起來很不正確,即垃圾爲什麼會這樣呢?最後我終止了字符串,但是我看到了垃圾值和堆棧損壞錯誤,不知道我的邏輯有什麼問題。

(I附上相同的快照)

memset invalid value

+3

「最後我終止了字符串」您的屏幕截圖顯示終止字符串的行尚未執行。 – tkausl

+0

我null終止它爲了增加安全性我memset它的權利在一開始,但我看到垃圾字符串 –

+1

是的,但字符串不是null終止。這將是一行之後。 –

回答

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的緩衝區。)

+0

254與0xFD有什麼關係?看起來像是一個偏離1的情況。 – chux

+1

@chux,我的猜測是文檔中的一個錯字。 –

2

@Harry Johnston精細答案解釋什麼地方出了錯。


要墊的字符串其陣列尺寸,建議:

1)免除的'\0'memset(buff, ...);... strncpy_s(buff,...過度寫入),它們隨後用數據寫入。

2)使用size_t作索引數組,字符串數學。 size_t是該作業的正確大小整數。

3)當出現很糟糕的形式調用時,比如使用長於目標的鍵盤或大小爲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); 
相關問題