2009-06-03 22 views
5

Trong đoạn mã dưới đây, các dòng:lỗi Segmentation - char trỏ

*end = *front; 

đưa ra một lỗi phân khúc. Tôi hỏi một câu hỏi tương tự here nhưng tôi không chắc chắn nếu điều này là bởi vì tôi có hai bản sao của num. Vui lòng giải thích lý do tại sao nó bị lỗi. Cảm ơn bạn.

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

char* getPalin(char* num); 

int main() 
{ 
    char* num = (char*)malloc(100); 

    num = "123456"; 

    printf("%s\n", getPalin(num)); 

    return 0; 
} 

char* getPalin(char* num) 
{ 
    int length = strlen(num); 

    if (length % 2 == 0) 
    { 
     char* front = num; 
     char* end = num + strlen(num) - 1; //pointer to end 

     while(front != num + (length/2)) //pointers not middle yet 
     { 
      *end = *front; 

      printf("%c", *end); 

      front++; 
      end--; 
     } 
    } 

    return num; 
} 

Trả lời

15

Hai dòng này:

char* num = (char*)malloc(100); 
num = "123456"; 

có hiệu lực thi hành sau.

Đầu tiên phân bổ 100 byte và đặt num để trỏ đến các byte đó.

Thay đổi thứ hai num để trỏ đến chuỗi "123456" gần như chắc chắn trong bộ nhớ chỉ đọc.

Mọi nỗ lực thay đổi nội dung của bộ nhớ chỉ đọc sẽ dẫn đến vi phạm phân đoạn. Bạn cần phải sao chép chuỗi vào malloc 'd num trước khi cố gắng thay đổi nó, với:

strcpy (num, "123456"); 

Đó là dòng bạn nên có nơi bạn đang có:

num = "123456"; 
4

Sử dụng

strncpy(num, "123456", 100); 

thay vì

num = "123456"; 
+0

xin lỗi, không phải sizeof (num), nhưng kích thước của bộ nhớ được phân bổ, tức là 100. I.e. strncpy (num, "123456", 100); – Konstantin

+3

OP yêu cầu giải thích nhưng bạn đã đưa ra một giải pháp. Và không bao giờ quên tự thêm null-terminator sau khi strncpy vì nó không được đảm bảo rằng strncpy thêm nó. Tôi biết nó không có liên quan trong ví dụ này bởi vì "123456" ngắn hơn 100 byte nhưng nếu bạn quyết định sử dụng strncpy hơn là strcpy, hãy sử dụng nó đúng cách - bạn đã tránh được một vấn đề tiềm tàng (tràn bộ đệm) nhưng đã giới thiệu một chuỗi khác (chuỗi chưa hoàn thành) . – qrdl

+0

@qrdl - Miễn là kích thước đích được chỉ định trong strncpy lớn hơn độ dài chuỗi, strncpy sẽ tự động xóa bằng các ký tự null. Chỉ khi kích thước đích được xác định là nhỏ hơn chiều dài chuỗi cần sao chép thì có thể bỏ qua trình kết thúc null. Một piont khác là hãy nhớ rằng strncpy sẽ KHÔNG kiểm tra xem có đủ không gian trong bộ nhớ đích hay không. Vì vậy, tôi cho rằng strncpy (num, "123456", sizeof (num)) sẽ chính xác hơn. – ChrisBD

1

Như mỗi câu trả lời Konstantin của.

Bạn đã cấp phát bộ nhớ cho num với câu lệnh malloc.

Nếu bạn đã không thì bạn có thể nhận được ngay với:

char* num = "123456"; 

Trong đó sẽ xác định và phân bổ bộ nhớ một cách nhanh chóng nhưng nó sẽ rất có thể được phân bổ như một hằng số và do đó chỉ đọc.

Sử dụng strncpy thay vì strcpy để sao chép "123456" sẽ đảm bảo rằng bất kỳ không gian thừa nào ngoài phần cuối của chuỗi null terminator cũng được khởi tạo thành null, miễn là bạn chỉ định n là 100 (ví dụ). Nếu không, không khởi tạo bộ nhớ được cấp bởi malloc thành null (memset (num, 0, 100)) thì có thể hiểu được rằng bạn có thể vượt ra ngoài phần cuối của chuỗi.

Ồ gần như quên mất. Bạn nên sử dụng strcpy_s hoặc strncpy_s vì chúng an toàn hơn, mặc dù mã của bạn không quan trọng.

+0

Tôi thực sự xem xét hai hàm _s() này là một cái nạng cho những người không biết cách mã hóa bảo vệ [tức là, kiểm tra điều kiện tiên quyết trước - tôi chưa bao giờ thấy cần sử dụng strncpy() và mã của tôi vẫn là là "an toàn" như bất kỳ bằng cách sử dụng biến thể _s()]. Trên hết, chúng chưa phải là một phần của tiêu chuẩn. – paxdiablo

+0

Do đó lý do tại sao tôi nói nên. Nó không bao giờ ngừng làm tôi kinh ngạc bao nhiêu phần mềm thương mại lá chính nó mở cửa cho các cuộc tấn công tràn bộ đệm. – ChrisBD

0

Lý do cho lỗi này là:

char* num = (char*)malloc(100); 

Trong dòng này bạn đã tuyên bố num như một con trỏ đến một mảng hoặc con trỏ đến phần tử đầu tiên của nó không phải là một chuỗi.

num = "123456"; 

Dòng này bạn đã sử dụng num như bạn đã khai báo dưới dạng chuỗi.Điều này vi phạm phân đoạn và do đó lỗi seg. Các preferrable (đúng) cú pháp cho mã của bạn là:

char num[100]; 
    strcpy(num,"123456"); //Even if you use num="123456"; here it would still be wrong 

HOẶC

char* num = (char*)malloc(100); 
    strcpy(num,"123456"); 

HOẶC

char num[100]={'1','2','3','4','5','6'}; 

Bất kỳ trong số này sẽ làm công việc của bạn.

Các vấn đề liên quan