[英]Still getting “stack smashing detected” error even getting correct output
對於分配,我正在使用已經構建的3個函數( findString
, removeString
, insertString
)來構建replaceString
函數,該函數將s1
字符串在source
字符串中的第一次出現替換為s2
字符串。 效果很好,除非s1
是單個字符(例如"a"
)或空字符串""
,否則錯誤“堆棧已檢測到堆棧”將顯示在下面:
hello, world
*** stack smashing detected ***: /home/noob/ex1008 terminated
======= Backtrace: =========
...
======= Memory map: ========
...
當我這樣調用函數時,就會發生這種情況:
char text[] = "a world";
replaceString ( text, "a", "hello," );
要么
char text[] = " world";
replaceString ( text, "", "hello," );
但是,當我這樣聲明數組長度時,可以消除此錯誤:
char text[10] = "a world";
replaceString ( text, "a", "hello," )
或者,如果s1的長度大於1:
char text[] = "the world";
replaceString ( text, "the", "hello," )
我不明白為什么會這樣。 輸入單字符串或空字符串時,是否有不需要聲明數組長度的方法? 請參閱下面的完整代碼:
#include <stdlib.h>
#include <stdio.h>
int main ( int argc, char *argv[] )
{
char text[] = "a world";
void replaceString ( char source[], const char s1[], const char s2[] );
replaceString ( text, "a", "hello," );
printf ( "%s\n", text );
return EXIT_SUCCESS;
} /* ---------- end of function main ---------- */
/*
* === FUNCTION =========================================================
* Name: replaceString
* Description: Replaces first occurrence of s1 in source with s2.
* ========================================================================
*/
void replaceString ( char source[], const char s1[], const char s2[] )
{
int start, removeLength;
int findString ( const char source[], const char search[] );
void removeString ( char source[], const int start, const int remove );
void insertString ( char source[], const char insert[],
const int start );
start = findString ( source, s1 );
if ( start == -1 )
return;
for ( removeLength = 0; s1[removeLength]; removeLength++ );
removeString ( source, start, removeLength );
insertString ( source, s2, start );
} /* ----- end of function replaceString ----- */
/*
* === FUNCTION =========================================================
* Name: findString
* Description: Determines if one character string exists inside other
* string. If found, returns location in source string. If
* not, returns -1.
* ========================================================================
*/
int findString ( const char source[], const char search[] )
{
int i, j;
for ( i = 0; source[i]; i++ )
for ( j = 0; source[i + j] == search[j] || ! search [j]; j++ )
if ( ! search[j] )
return i;
return -1;
} /* ----- end of function findString ----- */
/*
* === FUNCTION =========================================================
* Name: removeString
* Description: Removes a specified number of characters from a character
* string.
* ========================================================================
*/
void removeString ( char source[], const int start,
const int remove )
{
char output[80];
int i, j = 0;
for ( i = 0; source[i]; i++ )
if ( i < start || i >= start + remove )
output[j++] = source[i];
output[j] = '\0';
for ( i = 0; output[i]; i++)
source[i] = output[i];
source[i] = '\0';
} /* ----- end of function removeString ----- */
/*
* === FUNCTION =========================================================
* Name: insertString
* Description: Inserts a string into another string.
* ========================================================================
*/
void insertString ( char source[], const char insert[],
const int start )
{
char output[80];
int i = 0, j = 0, k = 0;
while ( source[i] ) {
if ( i < start || ! insert[k] )
output[j++] = source[i++];
else
output[j++] = insert[k++];
}
output[j] = '\0';
for ( i = 0; output[i]; i++ )
source[i] = output[i];
source[i] = '\0';
} /* ----- end of function insertString ----- */
當你做
char text[] = "a world";
您創建的數組只有8個字符(字符串和結尾的零)。 當用"hello"
替換子字符串"a"
,您將寫出數組末尾,從而“破壞”堆棧。
而是設置數組的大小,使其足夠大以適合替換,例如
char text[16] = "a world";
超出數組末尾(或超出任何已分配內存的末尾)的寫操作會導致未定義的行為 。 未定義的行為可能很容易彎曲,很難追蹤,因為有時它似乎確實可以按預期工作。
char text[] = "a world";
創建一個數組。 它的長度由其初始化程序決定,該初始化程序的長度為8個字符(不要忘記空終止符!)。 您要用五個字符替換一個字符,總共12個字符。對於數組而言,這太長了,所以溢出了。 那砸了堆棧。
您正在通過char text[] = "a world";
在堆棧上分配固定寬度的字符串char text[] = "a world";
,編譯器會在構建時自動確定為該r / w內存分配的空間量,該空間量是字符串的長度加上一個終止NULL字符的空間,在此特定示例中總計為8個字節。
您的代碼將嘗試在此內存區域的范圍之外進行寫入,並通過將其不應寫入的區域寫入堆棧而破壞堆棧,這也稱為堆棧粉碎。
您應該花一些時間來閱讀有關內存分段的信息,如下面的參考所述。 此外,如果堅持使用靜態分配緩沖區而不是通過malloc
/ calloc
調用在堆上動態分配malloc
,那么一個好習慣就是通過宏使用公共常量,如果編譯器為C99,則使用const size_t
兼容並支持可變長度數組(VLA)。
即:
#define MAX_BUF_LENGTH (1024)
char text[MAX_BUF_LENGTH] = "a world";
您將使用更多的內存空間,但是可以通過strlcat
, strlcpy
等編寫更安全的代碼,這使您可以安全地保證寫入的最大字節數,以防止將來發生此類錯誤。 參考文獻
<https://stackoverflow.com/questions/16021454/difference-between-declared-string-and-allocated-string/16021546#16021546>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.