簡體   English   中英

my_strcpy給出段錯誤

[英]my_strcpy gives seg fault

#include<stdio.h>

char* my_strcpy(char*,const char*);

int main(){
        char a[20];
        char* s = "Hello world!";
        char* d = a;
        my_strcpy(d,s);
        printf("\n d : %s \n",d);
        return 0;
}

char* my_strcpy(char* dest,const char* sour){
        if(NULL == dest || NULL == sour){
                return NULL;
        }
        while(1){
                *dest++ = *sour++;
                if(*sour == '\0'){
                        *dest = *sour;
                        break;
                }
        }
}

為什么我們需要char *作為my_strcpy的返回類型。 如果d為“”,則會出現分割錯誤。 如果我給它賦值,它就可以正常工作。 給定“”時,為什么會出現段錯誤。

修改:答案之后

#include<stdio.h>

char* my_strcpy(char*,const char*);

int main(){
        char* ret;
        char a[20];
        char* s = "Hello world!";
        char* d = "";
        ret = my_strcpy(d,s);
        if(NULL == ret){
                perror("\nret");
        }
//      printf("\n d : %s \n",d);
        return 0;
}

char* my_strcpy(char* dest,const char* sour){
        char* temp;

        if(NULL == dest || NULL == sour){
                return NULL; 
        }

        temp = dest;
        while(1){ 
                *temp++ = *sour++;
                if(*sour == '\0'){
                        *temp = *sour;
                        break;
                }
        }
        return temp;
}

這仍然會產生段錯誤。 傳遞給函數strcpy時,如果s =“”,該如何處理條件。

您問:“如果d為“,則表示分割錯誤。” 答案:如果為d分配“”或“”,將沒有足夠的空間容納“ Hello World”。 此外,如果將常量字符串分配給標記為數據的內存頁,則可能不允許修改。

您問“為什么我們要把char *作為my_strcpy的返回類型”作為我假定的原始strcpy。 答:您不必。 您可以將void作為返回類型。 但是,如果要執行以下操作,它將變得很實用:

printf ("%s", strcpy (dest, sour));

更正的代碼:

    while(1){
            *dest++ = *sour++;
            if(*(sour-1) == '\0'){
                    break;
            }

或更好:

            while(*sour != '\0'){
                *dest++ = *sour++;
            }
           *dest = *sour;

正確:

 if(*dest == '\0'){

應該:

 if(*(dest - 1) == '\0'){

注意:

 *dest++ = *sour++;

相當於

*dest = *sour;
sour++;
dest++;

賦值后,您將增加dest ,因此您在未初始化a[]情況下在出現垃圾值的位置檢查\\0導致未定義的行為。 另外,您不會在while循環后返回。

您可以簡單地將函數編寫為:

char* my_strcpy(char* dest,const char* sour){
     if(NULL == dest || NULL == sour)
         return NULL;
    char* d = dest;
     while(*dest++ = *sour++)
        ;
     return d;
}

試試看!!

在這里:

  1. 將* sour的值分配給* dest
  2. 同時增加酸味和味覺,所以現在指向下一個字符
  3. 測試* dest現在是否為NUL以退出循環

如您所見,第3步從未初始化的內存中讀取。 您應該測試在遞增之前分配的值是否為NUL。

            *dest++ = *sour++;
            if(*dest == '\0'){
                    break;
            }

如果您傳入的目標是一個常量字符串,例如“”,則會出現段錯誤,因為字符串常量存儲在只讀內存中。 它們不能被修改。

這是一個簡單的版本:

char *my_strcpy(char *d, const char *s){
  int i=0;
  while(d[i++]=*s++)
    /*done inside condition*/;
  return d;
}

我建議將strcpy實現為:

char* my_strcpy (char* s1, const char* s2)
{
  char* return_val = s1;

  *s1 = *s2;

  while(*s2 != '\0')
  {
    s1++;
    s2++;
    *s1 = *s2;
  }

  return return_val;
}

始終避免在同一表達式中使用多個++語句。 從來沒有理由這樣做,它遲早會給您帶來一些未定義/未指定的行為錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM