2011-11-06 31 views
7

Tôi gặp phải một vấn đề rất lạ ngày hôm nay. Câu chuyện dài ngắn, hàm của tôi trả về một giá trị, người gọi nhận được một giá trị khác. Một nơi nào đó xung quanh mã của tôi Tôi có một cuộc gọi đến:Giá trị thay đổi hàm C khi trả lại. Ngăn xếp bị hỏng?

Message* m = NULL; 
m = connection_receive(c); 

đâu connection_receive được định nghĩa như sau:

Message* connection_receive(Connection* c) 
{ 
Message* k; 

    if (c->state == CON_STATE_AUTHENTICATED) 
    { 
     pthread_mutex_lock(&c->mutex_in); 

     if (g_queue_is_empty(c->in)) 
      k = NULL; 
     else 
      k = (Message*)g_queue_pop_head(c->in); 

     pthread_mutex_unlock(&c->mutex_in); 
     /* Until here, k is reachable and contains the correct data. */ 
     return k; 
    } 
    else 
     return NULL; 
} 

Dưới đây là một hoạt động gdb, tôi dừng lại ngay trước khi sự trở lại và ngay sau khi chuyển nhượng:

222   return k; 
(gdb) p k 
$1 = (Message *) 0x7ffff0000950 
(gdb) n 
226 } 
(gdb) n 
main() at src/main.c:57 
57    if (m) 
(gdb) p m 
$2 = (Message *) 0xfffffffff0000950 

Tất nhiên, nếu chúng tôi cố gắng truy cập 0xfffffffff0000950, chúng tôi sẽ nhận được lỗi phân đoạn.

Nếu tôi thay đổi hàm và thay vì trả về một giá trị, sử dụng thông số thứ hai để chuyển giá trị hoạt động, nhưng tôi muốn biết điều gì đã xảy ra trên giá trị này.

Cảm ơn bạn rất nhiều.

EDIT: Tính năng này hoạt động nhưng không thuận tiện. Và tôi cũng muốn biết tại sao lỗi lạ như vậy lại xảy ra.

void connection_receive2(Connection* c, Message** m) 
{ 
    if (c->state == CON_STATE_AUTHENTICATED) 
    { 
     pthread_mutex_lock(&c->mutex_in); 

     if (g_queue_is_empty(c->in)) 
      *m = NULL; 
     else 
      *m = (Message*)g_queue_pop_head(c->in); 

     pthread_mutex_unlock(&c->mutex_in); 
    } 
    else 
     *m = NULL; 
} 

EDIT2: Giải quyết. Cảm ơn tất cả. Sự cố là lỗi đánh máy trên tệp tiêu đề. Tôi không thể sử dụng -Werror vì tôi cần phải làm những việc mà tăng một số cảnh báo và trong một đầu ra lớn và tiêu đề lớn, tôi đã bỏ qua nó.

+0

Tôi đã xảy ra điều đó một lần. 'fin' cho thấy một giá trị trả về và biến nó được lưu trữ vào một giá trị khác. Một biên dịch đã sửa nó cho tôi (thậm chí không thay đổi nguồn gốc); tốt nhất tôi có thể đoán là một tập tin đối tượng phụ thuộc đã không nhận được biên dịch lại, nếu không có thể là một lỗi (hiếm khi gặp phải) trong gcc. – Kevin

+0

Bạn cần phải đun sôi điều này xuống [SSCCE] (http://sscce.org/) để minh họa sự cố và đăng nó - không có gì sai với mã bạn đã đăng; vấn đề nằm ở nơi khác. –

+0

@BrianRoach, tôi sẽ xem những gì tôi có thể làm. Đó là một dự án lớn. – Victor

Trả lời

5
  1. Cách xác định m của bạn?
  2. Người gọi có quyền truy cập vào nguyên mẫu phù hợp không?
  3. Bạn đang sử dụng kiến ​​trúc nào?

Tôi nghi ngờ rằng có sự không phù hợp với các loại và câu hỏi của tôi 2 là mấu chốt của tất cả.

Bạn đang trả lại con trỏ với (tôi giả sử như vậy) 48 hoặc 64 bit. Người gọi, tuy nhiên, nghĩ rằng để có được một int, trong đó có thể 32 bit và được ký kết. Khi chuyển đổi trở lại con trỏ, giá trị sẽ được gia hạn ký.

+4

+1, tôi chắc chắn (2) là chính xác. Đây là lý do bạn nên luôn luôn phát triển với các cảnh báo biên dịch tối đa được thiết lập ('-Wall -Werror' trên gcc), vì nó sẽ bắt được loại điều này. –

+0

có, nửa dưới của giá trị trả về giống hệt nhau là rất đáng ngờ. –

+0

@therefromhere \t Tôi xin lỗi, tôi quên nói. "M" của tôi cũng là một tin nhắn *. Có, người gọi có quyền truy cập vào cùng một mẫu thử nghiệm, tôi đang thực sự thử nghiệm mô-đun. Không -Wall cũng không -Wextra cho tôi bất cứ điều gì, nó biên dịch như một sự quyến rũ. Tôi đang xây dựng và chạy nó trên Fedora 15, 2.6.40.6-0 64bits – Victor

0

Bạn đã đẩy đối tượng malloc: ed vào hàng đợi chưa? Nếu không và bạn thay vì đẩy một đối tượng ngăn xếp thì khi bạn có thể kết thúc với hành vi lạ khi bạn bật các mục.

+0

Đó là một đối tượng malloc'ed. Tôi đã chỉnh sửa bài đăng gốc và đăng một định nghĩa tương đương hoạt động tốt. Nó thực sự kỳ lạ! – Victor

0

Chúng tôi phải đối mặt với cùng một vấn đề và nguyên nhân gốc là khai báo ngầm của hàm connection_receive(). Vì vậy, nó đã được mặc định để int đã ký và sau đó được lưu trữ trong m.

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