2009-06-04 17 views
6

đầu mối nằm trong tiêu đề nhưng về cơ bản tôi đã thừa hưởng một số mã có hơn 800 trường hợp của strcpy. Tôi muốn viết một hàm mới và sau đó thay thế strcpy bằng strcpy_mine.strcpy ... muốn thay thế bằng strcpy_mine mà sẽ strncpy và null chấm dứt

Vì vậy, tôi đang cố gắng tìm ra danh sách tham số strcpy_mine sẽ có.

tôi đã cố gắng:

void strcpy_mine(char* pTarget, const char* const pCopyMe) 
{ 
    const unsigned int lenAlwaysFour = sizeof(pCopyMe); //:(
    strncpy(pTarget, pCopyMe, lenAlwaysFour); 

    //add extra terminator in case of overrun 
    pTarget[lenAlwaysFour] = 0; 
} 

nhưng sizeof phải lúc nào cũng 4 pCopyMe là một con trỏ

những gì tôi không muốn làm là thay thế

strcpy (buf, pCopyMe); 

với

strncpy (buf, pCopyMe, sizeof(pCopyMe)); buf[sizeof(pCopyMe)] = 0; 

bất kỳ ý tưởng nào? (Strcpy_l không có sẵn)

cổ vũ

Trả lời

4

Tùy thuộc vào cách gọi các trang web như thế nào, thường đa số trường hợp có thể được xử lý bởi một mẫu đơn giản:

#include <string.h> 

template <int bufferSize> 
void strcpy_mine(char (&pTarget)[bufferSize], const char* const pCopyMe) 
{ 
    strncpy(pTarget, pCopyMe, bufferSize-1); 

    //add extra terminator in case of overrun 
    pTarget[bufferSize-1] = 0; 
} 

int main() 
{ 
    char buf[128]; 
    strcpy_mine(buf,"Testing"); 
    return 0; 
} 

Nếu bạn đang sử dụng Microsoft Visual Studio 2005 hoặc mới hơn, xem Secure Template Overloads cho một thi Microsoft .

+0

cổ vũ!đây gần như là những gì tôi theo sau, nhưng nó vẫn buộc tôi đặt kích thước của bộ đệm bằng chữ V mặc dù char buf [200]; strcpy_mine <200> (buf, pString); – timB33

+0

strCpyMine (buf, pString); – timB33

+0

Sau đó, bạn đang làm điều gì đó sai trái. Trình biên dịch lỗi thời? – MSalters

11

sizeof() trả về kích thước của các loại - trong trường hợp này const char* const đó sẽ có 4 trên máy 32-bit.

Tôi nghĩ bạn nghĩ bạn muốn strlen(). Nhưng đó không phải là cách thích hợp để sử dụng các hàm strncpy. Bạn cần kích thước của đầu ra bộ đệm cho strncpy.

Để khắc phục điều này, bạn cần phải kiểm tra mã tại mỗi trang web cuộc gọi và tìm ra kích thước của bộ đệm đầu ra và chuyển đối số đó làm đối số cho strcpy_mine. Nếu call-site cho strcpy (hoặc strcpy_mine) không biết kích thước của bộ đệm đầu ra, bạn cần phải tìm kiếm ngược trong mã cho vị trí phân bổ bộ đệm, và vượt qua kích thước tất cả các con đường xuống trang web strcpy . Về cơ bản bạn không thể viết một sự thay thế cho strcpy có cùng các đối số và hy vọng sẽ tránh được các vấn đề được tạo ra strncpy ngay từ đầu (và thay thế tốt hơn thế nữa). Bạn có thể tạo một hàm lấy các đối số giống như strncpy, nhưng đảm bảo kết quả là null-terminated - xem xét việc thực hiện hàm OpenBSD's strlcpy(). Nhưng bước đầu tiên là phải thay đổi các trang web gọi để truyền đạt kiến ​​thức về kích thước bộ đệm đầu ra.

+0

+1 cho strlcpy. Bằng văn bản chức năng của riêng tôi tương tự như thế này tôi cũng vượt qua một enum {AllOrNothing, TruncateOkay} để chức năng để làm cho nó xử lý các trường hợp tràn. – Dolphin

1

Bạn có thể sử dụng cùng một danh sách tham số như strncpy cho strcpy_mine của bạn, nhưng viết nó để nó luôn vô hiệu kết quả. Không nên rất khó làm.

Một thách thức, tuy nhiên, một số mã hiện có của bạn gọi strcpy() cũng không biết kích thước của bộ đệm.

+0

Tôi thứ hai này. Bạn sẽ cần phải thêm một tham số khác cho kích thước của bộ đệm đầu ra. Phương pháp strcpy là một nguồn tràn bộ đệm lỗi cổ điển. Microsoft thậm chí còn phản đối chức năng này để ủng hộ một thứ như strncpy. – Mark

0

Ngoài ra, bạn có thể sử dụng macro để tránh nhiều lần chỉnh sửa. Hoặc tự động chỉnh sửa qua một số tập lệnh.

+0

Trong trường hợp bạn quan tâm, macro là số ít, macro là số nhiều. Macro không phải là một từ. Tôi đoán tiếng Anh không phải là ngôn ngữ mẹ đẻ của bạn. Tôi chỉ cố gắng giúp bạn. – jmucchiello

0

Bạn chắc chắn cần phải vượt qua kích thước của bộ đệm đích làm tham số, như những người khác đã nói ở trên.

Đây là loại chủ đề, nhưng tôi chỉ muốn chỉ ra rằng, sau khi bạn sử dụng strncpy(), bạn cần đặt thành rỗng ký tự cuối cùng của bộ đệm, có chỉ số 1 ít hơn so với độ dài (không phải là chiều dài của bộ đệm):

strncpy (buf, pCopyMe, buflen); buf[buflen - 1] = '\0'; 

Hoặc cách khác, bạn có thể sử dụng strncat() về một chuỗi rỗng, đi qua nó một chiều dài đó là 1 ít, và nó sẽ đảm bảo để null-chấm dứt chuỗi của bạn:

buf[0] = '\0'; strncat (buf, pCopyMe, buflen - 1); 
+0

nếu u là anyway tại sao không: strncpy (buf, pCopyMe, buflen) [buflen-1] = '\ 0'; :-) –

+0

@Anders: Cool !!! – jmucchiello

0

Douglas Leeder đã đúng. Có một giới hạn về tính hữu ích của việc thay thế strcpy trừ khi bạn sẵn sàng thực hiện công việc grunt của việc truyền trong một chiều dài đệm tốt, sane ở mỗi và mọi thể hiện. Đó là rất nhiều công việc!

Tin vui là, đáng giá! Quay lại một vài năm trước, tôi đã tham gia vào một số dự án C++ đã bị trễ, lỗi và không đáng tin cậy. Bằng cách tuyên bố strcpy và strlen bị cấm, và mất 2-3 ngày trong dự án để thay thế chúng bằng strncpy/strnlen tùy chỉnh, trong tất cả các dự án này, chúng ta đột nhiên có thể chạy trong nhiều ngày thay vì hàng giờ. Chúng tôi cũng thấy rất nhiều chuỗi bị cắt ngắn xuất hiện trên màn hình và các tệp nhật ký. Điều đó đã cho chúng tôi manh mối cần thiết để theo dõi các vấn đề cắt ngắn, trước đây là sự cố. Nếu bạn không muốn làm điều này, bạn có thể nhận được một lợi ích nhỏ hơn nhiều bằng cách chỉ cần kiểm tra cả hai tham số con trỏ cho NULL, và giới hạn kích thước tối đa của một chuỗi sao chép và ghi lại tất cả các lần mà ranh giới đạt được. Không được thực hiện một chuỗi thông số nào, vì strlen sẽ gặp sự cố với bạn nếu chuỗi không được kết thúc đúng cách.

Ngày nay, các dự án mới sử dụng các đối tượng chuỗi tốt, nhưng có rất nhiều mã kế thừa không có.

2

Có lẽ hơi ngoại vi, nhưng vì không ai đề cập đến nó và nó được khoe trong tiêu đề: bạn không thể (hợp pháp) viết chức năng toàn cầu được gọi là strcpy_mine().

"Không gian tên" của các hàm có tên bắt đầu bằng str được dành riêng cho thư viện chuẩn. Xem, ví dụ: the accepted answer to this question.

+0

thú vị, chúc mừng :) – timB33

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