2009-07-31 41 views
6

Tôi đang sử dụng hàm gets() trong mã C của mình. Mã của tôi đang làm việc tốt nhưng tôi nhận được một thông điệp cảnh báoTắt thông báo cảnh báo trong GCC thông qua các tệp tiêu đề?

(.text+0xe6): warning: the `gets' function is dangerous and should not be used. 

tôi muốn thông điệp cảnh báo này không phải để bật lên. Không có cách nào khác ư?

Tôi tự hỏi rằng có thể có những khả năng như vậy bằng cách tạo tệp tiêu đề để vô hiệu hóa một số cảnh báo. Hoặc có bất kỳ tùy chọn nào trong quá trình biên dịch có thể phục vụ mục đích của tôi không? Hoặc có thể có cách sử dụng gets() để cảnh báo này không bật lên?

Trả lời

27

Câu trả lời rõ ràng là tìm hiểu từ những gì trình biên dịch đang cố gắng cho bạn biết - bạn sẽ không bao giờ sử dụng được(), vì nó hoàn toàn không an toàn. Sử dụng fgets() để thay thế, cho phép bạn ngăn chặn tràn bộ đệm có thể xảy ra.

#define BUFFER_SIZE 100 
char buff[BUFFER_SIZE]; 
gets(buff); // unsafe! 
fgets(buff, sizeof(buff), stdin); // safe 
+0

Cảm ơn Neil ... fgets hoạt động tốt. cảm ơn rất nhiều. –

+3

Trong thực tế, bạn có thể sẽ muốn sử dụng 'sizeof buff' thay vì nhân đôi kích thước bộ đệm. –

+3

Trong cuộc sống thực, bạn sẽ muốn kích thước bộ đệm thông qua một hằng số như BUFFSIZE và cũng sử dụng nó trong lệnh fgets(). –

10

Tôi sẽ chú ý đến cảnh báo và thay thế gets. Đây là đủ rõ ràng cho tôi:

LỖI

bao giờ sử dụng được(). Bởi vì không thể biết được dữ liệu trong số trước số ký tự được() sẽ đọc và vì() sẽ tiếp tục lưu trữ ký tự ở cuối bộ đệm, việc sử dụng cực kỳ nguy hiểm. Nó có được sử dụng để phá vỡ bảo mật máy tính. Sử dụng fgets() để thay thế.

8

Sử dụng fgets() thay vì nhận được()

char buffer[BUFSIZ]; 
/* gets(buffer); */ 
fgets(buffer,sizeof(buffer), stdin); 

Các nhận() chức năng không kiểm tra độ dài của bộ đệm và có thể viết qua cuối cùng và thay đổi chồng. Đây là "tràn bộ đệm" mà bạn nghe.

5

Bạn hoàn toàn không nên sử dụng chức năng gets, trang manpage cho biết sử dụng fgets để thay thế.

GCC không cung cấp chức năng mà GCC thực hiện để tắt cảnh báo bằng cách sử dụng pragmas. Bạn phải sử dụng warning options khác nhau làm cờ cho trình biên dịch thay thế.

+0

Cảnh báo này được cung cấp bởi trình liên kết. Tôi không biết cách tắt nó. – AProgrammer

6

Thực sự không có lý do chính đáng để sử dụng gets(). Ngay cả tiêu chuẩn C cũng nói rằng nó đã lỗi thời! Sử dụng fgets() để thay thế.

[Chỉnh sửa]

Dường như cảnh báo đến từ trình liên kết. Bạn có nhận được cảnh báo khi biên dịch với -c không? (Điều này vô hiệu hóa liên kết.)

24

Nếu bạn thực sự muốn sử dụng nó.

Dưới đây là câu trả lời Từ: http://www.gamedev.net/community/forums/topic.asp?topic_id=523641

Nếu bạn sử dụng một phiên bản mới một cách hợp lý của gcc, bạn có thể sử dụng:

#pragma GCC diagnostic ignored "your option here" 

Ví dụ, nếu những tiêu đề sản xuất một "so sánh dấu chấm động không an toàn" lỗi, bạn sẽ sử dụng:

#pragma GCC diagnostic ignored "-Wfloat-equal". 

Thật không may, bạn không thể tắt "-Wall" theo cách đó (quá dễ, không phải ...), bạn phải làm cuộc chiến cá nhân tùy chọn ning -Wall cho phép bằng tay (ít nhất, các xung đột).

Documents: http://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas

EDIT: Nhưng nó dường như không làm việc cho được cảnh báo ... Tôi đã thử trên máy của tôi.

+3

+1 Mặc dù tôi đồng ý rằng() không được sử dụng, bạn là người duy nhất thực sự trả lời câu hỏi của OP :) – qrdl

+4

Điều này chỉ hoạt động đối với các chẩn đoán do trình biên dịch * phát hành *. Thông điệp "không an toàn" xuất phát từ * linker * và AFAIK không có cách nào để vô hiệu hóa nó. – zwol

-2

Trái với ý kiến ​​phổ biến, không phải tất cả các lập trình viên đều không chú ý đến những gì họ đang viết. gets() sẽ luôn luôn là tiêu chuẩn trong C90, và nó đã được đưa vào thư viện vì một số lý do tốt. Nó không còn "nguy hiểm" hơn bất kỳ chức năng chuỗi nào khác khi được sử dụng một cách thích hợp, chẳng hạn như trong ví dụ chương trình, tài liệu, giàn giáo thử nghiệm đơn vị, bài tập về nhà, v.v.

Tăng cường khả năng đọc theo cách fgets(). Và người ta không bao giờ phải ngắt lời đào tạo của một người để tìm kiếm thứ tự để đưa ra lý lẽ của mình.

Cách giải quyết sau đây sử dụng chức năng yêu thích khác của tôi để xóa dòng mới. :)

#define gets GET_LOST 
#include "stdio.h" 
#undef gets 

#include "limits.h" 

char *gets(char *s) 
{ 
    return strtok(fgets(s, INT_MAX, stdin), "\n"); 
} 
+8

Ai ký một câu trả lời SO với tên, số điện thoại và ngày của họ? – bgw

+0

Nếu đầu vào của người dùng chỉ bao gồm ''\ n'', thường trình này trả về' NULL'. Original 'gets()' trả về '" "'. – chux

1

Đề xuất thay thế an toàn cho gets().

Trong mã hiện có, để thay thế gets(), nó có thể không được mong muốn sử dụng fgets() như chức năng mà đòi hỏi thêm một char để lưu '\n' mà cả hai chức năng tiêu thụ, nhưng gets() không lưu. Sau đây là một thay thế không yêu cầu kích thước bộ đệm lớn hơn.

Mỗi gets(dest) là thay bằng:
Nếu dest là một mảng, sử dụng gets_sz(dest, sizeof dest)
Nếu dest là một con trỏ đến một mảng char kích thước n, sử dụng gets_sz(dest, n)

char *gets_sz(char *dest, size_t size) { 
    if (size <= 1) { 
     if (size <= 0 || feof(stdin)) { 
      return NULL; 
     } 
    } 
    size--; 
    size_t i; 
    for (i = 0; i < size; i++) { 
     int ch = getchar(); 
     if (ch == EOF) { 
      if (i == 0) 
       return NULL; 
      break; 
     } 
     if (ch == '\n') 
      break; 
     dest[i] = (char) ch; 
    } 
    dest[i] = 0; 
    return dest; 
} 
0

Nếu bạn thực sự muốn sử dụng hãy thử cờ -fsyntax-only.

Tài liệu hướng dẫn trong gcc website nói:

-fsyntax-only

Check the code for syntax errors, but don't do anything beyond that. 
Các vấn đề liên quan