2009-03-12 40 views
8

Tôi thường nghe nói rằng C có thể sụp đổ một cách ngoạn mục. Gần đây tôi đã có được hương vị đầu tiên của tôi về điều này khi một chức năng tôi mong đợi để trả về một chuỗi thay vì trả lại ít khuôn mặt hạnh phúc. Kể từ đó tôi đã được cẩn thận hơn với khởi tạo con trỏ và bộ nhớ mallocing cho mảng. Tuy nhiên, tôi vẫn gặp khó khăn khi tin rằng một chương trình có thể sụp đổ RATNG xấu ...mức độ nghiêm trọng có thể gây ra sự cố?

Tôi đoán nó sẽ phụ thuộc vào phạm vi của chương trình? Ý tôi là, nếu một lỗi trong chương trình xử lý với fan của bạn sao chép khuôn mặt hạnh phúc vào một số không gian quan trọng trong bộ nhớ ...?

Câu hỏi của tôi là, có bao nhiêu huyền thoại trong thế giới của các sự cố C ngoạn mục? Tôi có thể lấy một số ví dụ cụ thể về những điều nguy hiểm mà người ta phải tránh không?

z.

+7

"... trả lại ít khuôn mặt hạnh phúc", ít nhất nó đã chết với một nụ cười trên khuôn mặt của nó? – David

+0

Có thể muốn thêm vào thực tế là bạn đang chạy trên Nintendo DS, như ý kiến ​​của mọi người, ý tưởng và đề xuất có thể hoàn toàn khác nhau dựa trên kịch bản đó. –

+0

bạn muốn nó sụp đổ đến mức nào? – user21714

Trả lời

8

Hệ điều hành ngăn các sự cố khủng khiếp nhất trong những ngày này. Điều tồi tệ nhất tôi từng làm là khóa cứng máy (chỉ cần khởi động lại bằng cách giữ nút nguồn) và tranh giành một vài tập tin.

Tất cả phụ thuộc vào tài nguyên bạn đang truy cập. Nếu bạn đang viết các tập tin, có một số cách cấu trúc thư mục có thể bị rối mà được sử dụng để gây nhầm lẫn cho các tiện ích hệ thống, nhưng hầu hết các vấn đề đó đã được sửa. Nếu bạn đang làm một cái gì đó như là người chủ, tốt, sau đó bạn có thể chắc chắn làm cho một mớ hỗn độn bởi vì nhiều tập tin hệ thống có thể ghi. Nếu bạn đang sử dụng mạng, có rất nhiều thứ có thể bị lỗi tương đối, nhưng không nhiều hơn việc sử dụng quá nhiều băng thông. Tất nhiên, một vài năm lập trình và bạn sẽ thấy tất cả các loại điều không chắc chắn.

Đối với hầu hết các phần, bạn có thể thử nghiệm và chơi xung quanh. Những ngày này các hệ thống đủ kiên cường mà bạn sẽ không tạo ra một mớ hỗn độn quá khó để thoát ra khỏi. Hệ điều hành giữ mỗi chương trình với một phần bộ nhớ riêng và không cho phép truy cập để thay đổi các hệ thống quan trọng trừ khi bạn là quản trị viên/root. Con trỏ lơ lửng trong vườn của bạn có thể in những thứ vui nhộn hoặc làm hỏng chương trình của bạn, nhưng nó sẽ không phá hủy một máy tính hiện đại.

Từ một bình luận trong bài trả lời khác: "Tôi đang sử dụng Nintendo DS để chạy chúng"

Ok, có vấn đề! (Đầu tiên: Ý tưởng tuyệt vời! Nghe có vẻ thú vị.) Mã hóa cho một cái gì đó như thế không giống nhau về những gì có thể đi sai như hầu hết mã hóa cho máy tính để bàn. Một cái nhìn ngắn gọn về tài liệu hướng dẫn cho libnds và một số hướng dẫn về lập trình Nintendo DS cho tôi biết rằng không có hệ điều hành để nói về. Vì vậy, tôi không có ý tưởng bao nhiêu bạn có thể làm với một con trỏ đi lạc, có lẽ rất nhiều. Có thể có điều gì đó gây tổn hại. Nó có thể là một ý tưởng tốt để săn lùng những người đã lập trình cho nền tảng đó trước đây, xem họ phải nói gì.

+0

Hmm yeah! Tôi đã chạy chương trình của tôi trên một trình mô phỏng DS, nhưng tôi sợ đến chết để thử nó trên DS của tôi. Tôi muốn những người libnds đọc Stackoverflow. – Ziggy

17

Tôi nghĩ rằng đó có lẽ là cách tồi tệ hơn trong những ngày bộ nhớ trước khi bạn có thể phá hủy bộ nhớ của các quá trình khác, nhưng ngày nay điều tồi tệ nhất có thể xảy ra thực sự là làm hỏng chương trình của riêng bạn. Thông thường thông qua lỗi phân đoạn từ con trỏ xấu.

Điều đó loại trừ tất nhiên thổi mọi thứ lên bằng cách lạm dụng tài nguyên hệ thống - bạn có thể làm điều đó bằng bất kỳ ngôn ngữ nào.

+0

Trừ khi bạn viết mã trên một thiết bị nhúng không có hệ điều hành hoặc viết trình điều khiển thiết bị OS. Trong trường hợp đó là niềm vui nếu tràn bộ đệm có thể ghi vào bộ nhớ được ánh xạ IO, khiến bạn xuất các giá trị thùng rác trên các chân IO đó, điều khiển tốc độ của môtơ và xoay nó lên .. – nos

10

Điều tồi tệ nhất đã xảy ra với tôi là tham nhũng bộ nhớ mà không gây ra một vụ tai nạn ngay lập tức, nhưng sau một thời gian .. làm cho nó khó khăn như vậy để phát hiện .. argh

+0

Tôi trở nên hoang tưởng về việc lạm dụng khẳng định một thời gian vì kịch bản giống như kịch bản của bạn, nơi một lỗi nhỏ bé nhỏ từ từ làm rò rỉ bộ nhớ hoặc dữ liệu bị hỏng dữ liệu âm thầm trong một khoảng thời gian. – David

5

Vâng, nếu bạn đang viết mã hạt nhân , đôi khi bạn có thể ghi đè lên các bit hệ thống quan trọng của bộ nhớ, chẳng hạn như các vectơ ngắt, bảng mô tả toàn cục, các bảng xử lý, gây ra tất cả các loại nội dung thú vị!

1

Nếu mã của bạn đang chạy trên một hệ điều hành từ xa hiện đại, bạn không thể sao chép khuôn mặt hạnh phúc vào điểm ngẫu nhiên trong bộ nhớ. Bạn có thể sụp đổ nhiều như bạn muốn, và nó sẽ chỉ dẫn đến việc chấm dứt quá trình của bạn.

Gần nhất bạn có thể thực sự làm rối loạn hệ thống của bạn đang lạm dụng tài nguyên bộ nhớ/bộ nhớ/đĩa hoặc sinh ra quá nhiều quy trình con mà hệ điều hành hết PID (nếu vẫn sử dụng giá trị 32 bit để lưu trữ) .

+0

Xem xét hệ điều hành phải phân bổ một ngăn xếp cho mỗi quá trình và đủ không gian trong bộ nhớ cho quá trình đó, tôi tưởng tượng bạn sẽ hết bộ nhớ trước khi hệ điều hành chạy hết PID. – dreamlax

3

Ngày nay kiểu C gặp sự cố khó khăn rằng cứng (trừ khi bạn đang mã hóa hạt nhân hệ điều hành hoặc giống như vậy).

Quay lại ngày DOS/Win95/Win98, bạn có thể tạo chương trình C chash thực sự, thực sự là. Tôi sử dụng để có được điều này rất nhiều:

Bất cứ khi nào tôi có hoạt động con trỏ nguy hiểm làm rối loạn bộ nhớ, tôi có một màn hình dựa trên nhân vật đầy đủ các loại ký tự, màu sắc khác nhau, một số, nhấp nháy !!! Tôi đoán các hoạt động sai lầm một cách nào đó với Video Memory.

Nhưng hôm nay, vì các quy trình chạy trong vòng an toàn hạt nhân, điều tồi tệ nhất bạn sẽ nhận được nếu quá trình của bạn biến mất.

5

C chính nó không thể sụp đổ bất cứ điều gì. Lập trình cẩu thả có thể làm hỏng mọi thứ.

"Khuôn mặt hạnh phúc" là dấu hiệu cho biết mã của bạn đã bị hỏng bộ nhớ. Điều duy nhất C phải làm với điều đó là thực tế là bạn đã chọn sử dụng nó. (Và thực tế hệ điều hành của bạn cho phép nó xảy ra là đáng ngạc nhiên - bạn vẫn đang chạy phiên bản DOS?)

+0

Eh, bạn vẫn có thể viết nguệch ngoạc trên bộ nhớ miễn là nó là của bạn: P Bạn cũng có thể đọc các con trỏ bộ nhớ trong quá khứ, một lần nữa, miễn là nó là của bạn! Vì vậy, bạn không cần phải chạy DOS chỉ để có được khuôn mặt cười để hiển thị! –

+0

Điểm chụp. Tôi đoán đã quá lâu kể từ khi tôi làm điều đó tôi sẽ không nghĩ rằng nó vẫn còn có thể. Lần cuối cùng nó xảy ra với tôi, IIRC đó là DOS 3.2, và tôi có khuôn mặt hạnh phúc và buồn và màu sắc nhấp nháy. :-) Khá hấp dẫn, thực sự. Tuy nhiên, –

+0

, tôi không sử dụng các cửa sổ để chạy các chương trình của mình, chỉ để biên dịch chúng. Tôi đang sử dụng Nintendo DS để chạy chúng, vì vậy tôi phải cẩn thận hơn! – Ziggy

12

Quay lại khi tôi đang học lập trình C++, trên hệ điều hành Mac 7 hoặc 8 tôi không hãy nhớ điều đó. Dù sao, nó không có bộ nhớ ảo được bảo vệ nên rất nhiều lỗi như để lại một con trỏ lơ lửng hoặc tràn bộ đệm sẽ khiến toàn bộ máy tính bị hỏng. Tôi nhớ rằng khi Apple lần đầu tiên công bố họ sẽ tạo ra một hệ điều hành mới mà đã được bảo vệ không gian bộ nhớ tại Macworld hoặc một cái gì đó, họ đã thể hiện mã nguồn cho một chương trình:

while (true) 
    *(int *)i++ = 1; 

Và khi họ chạy chương trình và chỉ chương trình chấm dứt, và không phải toàn bộ máy (nó có một thông điệp như "Bạn không cần phải khởi động lại máy tính của bạn") toàn bộ phòng đầy đủ các nhà phát triển apparantly burst vào vỗ tay. Dù sao, rõ ràng là không có bộ nhớ bảo vệ thực sự thực hiện lập trình C hoặc C++ thực sự khó khăn vì sự gia tăng mức độ nghiêm trọng của vụ tai nạn.

Ngày nay nó không phải là một việc lớn như vậy trừ khi bạn đang lập trình một cái gì đó chạy ở cấp độ giám sát, bạn không có khả năng sụp đổ hệ điều hành.

+4

Tôi đã viết một chương trình tương tự như vậy trên C-64 của tôi. Đó là "con rắn". Con rắn hợp lệ đi qua hàng đầu tiên, quấn qua hàng thứ hai, vv, và tắt đáy màn hình vào bất kỳ bộ nhớ nào theo sau vẽ những con rắn nhỏ và để lại khoảng trống. Cuối cùng nó ăn mã riêng của nó. Tai nạn. –

+0

Lol Tôi đã làm điều gì đó cực kỳ tương tự với c-64 –

+0

Những câu chuyện đó thật tuyệt vời! Lỗi khó hiểu lớn đầu tiên của tôi là tràn ngăn xếp gây ra bởi các trình lắng nghe chuột ngay lập tức bên trong một vòng lặp while. Trong khi vòng lặp! – Ziggy

1

Có một máy tính, Commodore PET 4032 (còn gọi là "Fat 40"), nơi thực sự có thể ghi vĩnh viễn chip video nếu bạn đưa giá trị sai vào phần sai của bộ nhớ. Bạn có thể tưởng tượng rằng nếu có một trình biên dịch C trên máy đó, một con trỏ hoang dã có thể thực sự gây ra thiệt hại vật lý không thể khắc phục cho máy tính.

6

Dưới đây là một đoạn nhanh chóng từ Henry "Mười điều răn cho C lập trình" của Spencer:

  • răn # 2 - Ngươi chớ làm theo con trỏ NULL, cho sự hỗn loạn và điên rồ đang chờ đợi ngươi tại kết thúc.
  • Rõ ràng thánh thư đã được phiên âm sai ở đây, vì các từ phải là `` con trỏ rỗng '', để giảm thiểu sự nhầm lẫn giữa khái niệm con trỏ null và macro NULL (trong đó có thêm anon). Nếu không, ý nghĩa là đồng bằng. Một con trỏ rỗng trỏ đến các vùng chứa đầy rồng, ma quỷ, các bãi lõi và vô số các sinh vật hôi khác, tất cả đều thích thú trong chương trình của bạn nếu bạn làm phiền giấc ngủ của chúng. Một con trỏ null không trỏ đến một 0 của bất kỳ loại nào, mặc dù một số mã cũ báng bổ mà impiously giả định này.

Đối với những người không quen thuộc với C, tôi nghĩ đoạn giới thiệu ngắn gọn nhất về C được thực hiện bởi "The Ten Commandments for C Programmers (Annotated Edition)" của Henry Spencer. Cách nó được viết thực sự được trao cho người đọc những mối nguy hiểm của C ... trong khi đồng thời là buồn cười (có nghĩa là người đọc sẽ thực sự chú ý nhiều hơn).

=========================

Cá nhân ... C không sụp đổ mà xấu khi bạn đang làm máy tính để bàn phát triển bởi vì bạn có sự sang trọng của seg-faulting. Seg-lỗi là khi hệ điều hành nhìn thấy bạn đang cố gắng REALLY F 'những thứ lên và nó nói "hey! Bạn không được phép có" và dừng quá trình.

Khi bạn đang thực hiện phát triển C được nhúng ... đó là khi bạn có được những thứ điên rồ thực sự ngoạn mục ... nghĩa là chúng YÊU CẦU bạn phải xoay vòng 99,9% thời gian. Giống như lần này, đoạn mã bằng cách nào đó làm lộn xộn cuộc gọi của tôi ... và sau đó bạn đang thực hiện một số chức năng ngẫu nhiên khác ... và sau đó ISR bằng cách nào đó vẫn đang diễn ra ... và phải mất 2 tuần để sửa lỗi đó lỗi.

0

Vâng, trở lại trong những ngày DOS, tôi quản lý để ghi đè lên một phần của khu vực khởi động - không có gì giống như khởi động lại để tìm "OS Không tìm thấy" hoặc bất kỳ thông điệp được.

Bạn học cách cứng được viết rất, rất cẩn thận vào đĩa sau đó ...

1

Trở lại trong những ngày DOS Tôi thực sự quá đã viết thông tin bios. Đã có được một công nghệ để sửa chữa nó. Máy tính gia đình đầu tiên của tôi - 286. Không thể khởi động sau một hoặc hai ngày.

0

C cho phép bạn xử lý máy khá gần trực tiếp. Làm thế nào ngoạn mục nó có thể sụp đổ là một chức năng của những gì máy có thể làm.

Vì vậy: Quy trình chế độ người dùng không có đặc quyền đặc biệt trong hệ điều hành hiện đại đẹp mắt sẽ không thực sự làm điều đó nhiều. Nhưng bạn có phần mềm khắp nơi. Hãy nghĩ về phần mềm điều khiển hệ thống phanh trong một chuyến tàu. Hãy nghĩ về phần mềm chạy hệ thống liên lạc khẩn cấp khi ai đó thực sự cần giúp đỡ. Hãy nghĩ về phần mềm chạy các biển báo trên đường cao tốc bận rộn. Hãy nghĩ về phần mềm chạy hệ thống tên lửa có hướng dẫn.

Có phần mềm ở khắp mọi nơi trong những ngày này. Rất nhiều nó được viết bằng C.

0

Quay lại khi tôi đang viết trình điều khiển Win98, BSOD đã ám ảnh tất cả mọi người.Tôi nhớ những sai lầm sau đây tôi đã thực hiện

typedef struct {_SOME_TAG_

int nSomeVar; 
    int nSomeMore; 
    ... 

} mystruct, * PMYSTRUCT;

.... PMYSTRUCT pMyStruct;

// Và tôi sử dụng cấu trúc này mà không phân bổ bất kỳ bộ nhớ nào ;-) pMyStruct-> nSomeVar = 0;

Và tai nạn lái xe đã rất khủng khiếp nhưng chúng tôi đã có một SoftICE từ Numega, Mặc dù nó chỉ là cách đây 10 năm .. Tôi cảm thấy lứa tuổi như nó lại

1

Trên bất kỳ hệ điều hành với bộ nhớ được bảo vệ điều tồi tệ nhất có thể xảy ra là quá trình của bạn bị treo. Bây giờ nếu quá trình của bạn xảy ra là một phần của hạt nhân hoặc một phần mở rộng hạt nhân thì bạn rõ ràng có thể sụp đổ toàn bộ hệ điều hành nhưng đó là điều tồi tệ nhất bạn có thể làm. Tuy nhiên, thực sự điều này giống với nhiều ngôn ngữ khác (ví dụ trong C deference một con trỏ null, trong java sử dụng một tham chiếu đối tượng được đặt thành null, cả hai sẽ làm hỏng quá trình của bạn).

Vì vậy, tôi tin rằng với bộ nhớ được bảo vệ, C không thể làm bất cứ thiệt hại nhiều hơn bất kỳ ngôn ngữ khác (trừ khi quá trình của bạn là một phần của hệ điều hành;))

+0

Tôi sẽ đặt cược điều tồi tệ nhất có thể xảy ra thực sự là với trình điều khiển;) – eglasius

2

trước khi bảo vệ bộ nhớ kiến ​​trúc, hầu hết các các vectơ nhảy được sử dụng bởi hệ điều hành được lưu trữ trong trang 0 của bộ nhớ (các địa chỉ bắt đầu từ số không)

ghi vào vị trí bộ nhớ trong trang zero - dễ dàng thay đổi vectơ nhảy của hệ điều hành , gây ra tất cả các loại hành vi tai nạn kỳ lạ - mọi thứ từ bàn phím bị khóa và màn hình video nhấp nháy đầy rác vào ổ cứng nhấp nháy điên cuồng, màn hình xanh chết, khởi động lại, v.v.

[mã hóa bằng ngôn ngữ assembly thậm chí còn thú vị hơn]

0

Quay lại trường đại học Tôi đã được giao nhiệm vụ tạo proxy đa luồng.

Thỉnh thoảng, proxy không phản hồi bất kỳ tài nguyên nào mà trang đã kéo. Mã gây ra sự cố:

Một số mã có sự cố tràn, sử dụng các biến gần trình xử lý tệp. Trước khi biết chuyện gì đang xảy ra, tôi thấy thật kỳ lạ khi di chuyển tờ khai xử lý tệp "cố định" vấn đề, lol.

Ps. kiểm tra này (không phải trong c, nhưng một câu chuyện tốt :)): http://trixter.wordpress.com/2006/02/02/computing-myth-1-software-cannot-damage-hardware/

0

Nếu phần mềm được đề cập đang chạy trên PC, nó có thể "đơn thuần" mang máy tính của bạn xuống.

Tuy nhiên, nếu nó được kiểm soát hoạt động của động cơ trong chiếc xe của bạn - hoặc tệ hơn, ABS - nó sẽ không chỉ là phần mềm bị treo ...

0

Một vụ tai nạn không phải là tồi tệ nhất điều có thể xảy ra.

Tôi đã đọc về chương trình nén tệp cũ của Unix (bạn biết đấy, như Zip) không kiểm tra giá trị trả về từ fclose. Có, fclose có thể trả về lỗi. Đầu ra cho một tập tin là bình thường đệm, vì vậy ngay cả khi một cuộc gọi đến fwrite hoặc putc dường như làm việc, và trả về OK, dữ liệu có thể vẫn còn trong một bộ đệm, chờ đợi để được viết.Khi fclose được gọi, bất kỳ dữ liệu không được ghi nào bị xóa, và điều này có thể bị lỗi, vì (ví dụ) đĩa có thể đã đầy. Và vì chương trình nén thường chạy chỉ đĩa đã gần đầy, điều này xảy ra khá thường xuyên. Vì vậy, chương trình âm thầm cắt ngắn tệp nén mới, tệp không nén ban đầu đã bị xóa và năm tiếp theo hoặc hơn khi ai đó cố gắng giải nén tệp, kết thúc bị thiếu!

Tôi nghĩ đây là một ví dụ tốt về lý do tại sao việc ném ngoại lệ có thể là điều tốt.

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