2012-01-30 51 views
5

Ở đây tôi muốn tạo bộ nhớ động. ở đây tôi không biết kích thước đầu ra và tôi muốn in cuối cùng cuối cùng đầu ra sau khi trong khi vòng lặp.Nhận lỗi phân đoạn trong Realloc

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

void main() { 

    char *sdpCommand = "sdptool browse 04:18:0F:B1:48:B5"; 

    FILE *fp; 
    fp = popen(sdpCommand, "r"); 

    char *results = 0; 
    if (fp == NULL) { 
     printf("Failed to run command\n"); 
     return; 
    } 

    char* buffer = malloc(514); 
    while (fgets(buffer, strlen(buffer) - 1, fp) != NULL) { 
     realloc(results, strlen(results) + strlen(buffer)); 
     memcpy(results + strlen(results), buffer, strlen(buffer)); 
    } 
    printf("Output ::: %s", results); 

    /* close */ 
    pclose(fp); 
    sleep(1); 

} 

Trả lời

11

Có hai vấn đề chính:

  1. realloc()lợi nhuận địa chỉ mới:

    new_results = realloc(results, ...); 
    if (new_results != NULL) { 
        results = new_results; 
    } else { 
        /* handle reallocation failure, `results' is still valid */ 
    } 
    
  2. sizeof() không phải là cách đúng đắn để tìm ra kích thước của results và của buffer. Nó sẽ đơn giản trả về kích thước của con trỏ . Đối với results, bạn có thể muốn tự theo dõi kích thước được phân bổ. Đối với buffer, có thể bạn đang tìm kiếm strlen().

Khi bạn sửa lỗi ở trên, bạn cần đảm bảo rằng results kết thúc dưới dạng chuỗi kết thúc NUL hợp lệ. Điều này là cần thiết cho printf() để hoạt động chính xác.

+2

... hoặc 'NULL' nếu việc phân bổ thất bại. – unwind

+0

Để xây dựng, 'sizeof (kết quả)' và 'sizeof (buffer)' trả về kích thước của các con trỏ mà thực sự được biết ở thời gian biên dịch. Không có cách nào trong tiêu chuẩn C để truy vấn kích thước của một khối được cấp phát động của bộ nhớ. Do đó bạn phải nhớ bạn đã phân bổ bao nhiêu. –

+0

Bạn có thể cho tôi biết nơi tôi phải thay đổi điều và mã của tôi hoạt động tốt không? – user1089679

2

Mã của bạn chỉ là một cách mù quáng giả mạo phía trước, dường như được viết theo mô hình "nó biên dịch, nó phải đang hoạt động". Tôi xin lỗi nếu điều đó nghe có vẻ khắc nghiệt, nó không phải là một bình luận về cá nhân bạn.

Bạn cần thực sự xem tại tài liệu hướng dẫn cho API: bạn đang cố gắng sử dụng và phân tích xem việc sử dụng của bạn có hợp lý hay không.

Bạn không thể bỏ qua giá trị trả lại từ realloc(), bạn sẽ nhận được bộ nhớ mới được cấp phát như thế nào? Nó không thể thay đổi con trỏ hiện tại của bạn, vì bạn đang chuyển nó theo giá trị.

Cách một mảng động nói chung cần phải làm việc là để theo dõi ba điều:

  • Mảng hiện tại của địa chỉ cơ sở
  • Số lượng các yếu tố (byte, trong trường hợp của bạn) mà mảng nắm giữ ngay bây giờ
  • số lượng các yếu tố đó mảng có thể giữ, tối đa (trước khi nó cần để phát triển)

Khi phụ n các yếu tố mới, bạn kiểm tra xem có làm như vậy làm tràn số lượng phần tử hay không, do đó, nó sẽ lớn hơn giá trị tối đa. Điều đó không được phép, vì vậy trong trường hợp đó, bạn cần phải phân bổ lại mảng cơ sở sao cho dữ liệu mới phù hợp, và (tất nhiên) cập nhật trạng thái của mảng cho phù hợp.

1

realloc (kết quả, sizeof (kết quả) + sizeof (bộ đệm));

Đường này có thể là vấn đề.

  1. realloc() trả lại địa chỉ mới được phân bổ với kích thước được chỉ định và không đảm bảo rằng nó sẽ là địa chỉ giống như con trỏ trước đây; Vì vậy, bạn nên luôn gán lại con trỏ của mình:

    ptr = realloc (ptr, newSize);

  2. sizeof() sẽ không trả lại kích thước được phân bổ động của con trỏ. Trong trường hợp này, sizeof(results)sizeof(buffer) có thể trở lại thường xuyên nhất 8. Bạn có thể thay thế bằng:

    kết quả = realloc (kết quả, ctr * 514);
    Trong đó ctr là short được khởi tạo với 0 trước số while và đếm số lần lặp lại.

  3. Kể từ đệm luôn luôn là 514 lý do tại sao bạn không giảm tải bởi redifining nó để:

    char buffer [514];

    Trân trọng

+0

Gán 0 cho con trỏ là hoàn toàn hợp lệ và tiêu chuẩn yêu cầu trình biên dịch gán 'NULL' cho con trỏ trong những trường hợp đó. –

+0

Tôi đã chỉnh sửa. Cảm ơn bạn – whitelionV