문제

나는 내 프로그램에 이상한 버그가 있습니다. Malloc ()가 Sigsegv를 일으키는 것으로 보입니다. 동적 목록을 위해 SimClist라는 라이브러리를 사용하고 있습니다.

다음은 나중에 참조되는 구조물입니다.

typedef struct {
    int msgid;
    int status;
    void* udata;
    list_t queue;
} msg_t;

그리고 여기 코드가 있습니다.

msg_t* msg = (msg_t*) malloc( sizeof( msg_t ) );

msg->msgid = msgid;
msg->status = MSG_STAT_NEW;
msg->udata = udata;
list_init( &msg->queue );

list_init 프로그램이 실패하는 곳입니다. List_Init의 코드는 다음과 같습니다.

/* list initialization */
int list_init(list_t *restrict l) {
    if (l == NULL) return -1;

    srandom((unsigned long)time(NULL));

    l->numels = 0;

    /* head/tail sentinels and mid pointer */
    l->head_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
    l->tail_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
    l->head_sentinel->next = l->tail_sentinel;
    l->tail_sentinel->prev = l->head_sentinel;
    l->head_sentinel->prev = l->tail_sentinel->next = l->mid = NULL;
    l->head_sentinel->data = l->tail_sentinel->data = NULL;

    /* iteration attributes */
    l->iter_active = 0;
    l->iter_pos = 0;
    l->iter_curentry = NULL;

    /* free-list attributes */
    l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *));
    l->spareelsnum = 0;

#ifdef SIMCLIST_WITH_THREADS
    l->threadcount = 0;
#endif

    list_attributes_setdefaults(l);

    assert(list_repOk(l));
    assert(list_attrOk(l));

    return 0;
}

라인 l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * 스택 추적에 따라 SIGSEGV가 발생하는 곳입니다. 디버깅을 위해 GDB/Nemiver를 사용하고 있지만 손실 중입니다. 이 기능이 처음이라고 불리는 것은 잘 작동하지만 항상 두 번째로 실패합니다. malloc ()가 어떻게 sigsegv를 유발할 수 있습니까?

이것은 스택 추적입니다.

#0  ?? () at :0
#1  malloc () at :0
#2  list_init (l=0x104f290) at src/simclist.c:205
#3  msg_new (msg_switch=0x1050dc0, msgid=8, udata=0x0) at src/msg_switch.c:218
#4  exread (sockfd=8, conn_info=0x104e0e0) at src/zimr-proxy/main.c:504
#5  zfd_select (tv_sec=0) at src/zfildes.c:124
#6  main (argc=3, argv=0x7fffcabe44f8) at src/zimr-proxy/main.c:210

모든 도움이나 통찰력은 대단히 감사합니다!

도움이 되었습니까?

해결책

malloc 예를 들어 힙이 손상되었을 때 예를 들어 Segfault 할 수 있습니다. 이전 할당의 범위를 넘어서는 것을 쓰지 않는지 확인하십시오.

다른 팁

아마도 메모리 위반은 코드의 다른 부분에서 발생할 수 있습니다. 당신이 리눅스에 있다면, 당신은 반드시 Valgrind를 시도해야합니다. Valgrind를 통과하지 않으면 내 자신의 C 프로그램을 결코 신뢰하지 않을 것입니다.

편집 : 또 다른 유용한 도구입니다 전기 울타리. glibc도 다음을 제공합니다 malloc_check_ 메모리 문제를 디버깅하는 데 도움이되는 환경 변수. 이 두 가지 방법은 Valgrind만큼 달리기 속도에 영향을 미치지 않습니다.

이 호출 전에 버퍼 오버플로 또는 free 할당되지 않은 포인터로 malloc (또는 이미 해방되었습니다).

Malloc에서 사용하는 내부 데이터 구조가 이런 식으로 손상되면 Malloc은 유효하지 않은 데이터를 사용하여 충돌 할 수 있습니다.

코어 덤프를 유발하는 무수한 방법이 있습니다. malloc() (그리고 realloc() 그리고 calloc()). 여기에는 다음이 포함됩니다.

  • 버퍼 오버 플로우 : 할당 된 공간의 끝을 넘어서 쓰기 (제어 정보 트램핑 malloc() 거기에 보관하고 있었다).
  • 버퍼 언더 플로우 : 할당 된 공간이 시작되기 전의 쓰기 (제어 정보 트램핑 malloc() 거기에 보관하고 있었다).
  • 할당되지 않은 메모리를 자유롭게합니다 malloc(). 혼합 된 C 및 C ++ 프로그램에서 C ++에 할당 된 프리링 메모리가 포함됩니다. new.
  • 할당 된 메모리 블록을 통해 부품을 가리키는 포인터를 제거합니다. malloc() - 이전 사례의 특별한 경우입니다.
  • 이미 해방 된 포인터를 해제 - 악명 높은 '더블 프리'.

진단 버전 사용 malloc() 또는 시스템 표준 버전에서 진단을 활성화하면 이러한 문제 중 일부를 식별하는 데 도움이 될 수 있습니다. 예를 들어, 작은 언더 플로우와 오버 플로우를 감지 할 수 있습니다 (요청한 공간 주위에 버퍼 영역을 제공하기 위해 추가 공간을 할당하기 때문에), 아마도 할당되지 않았거나 이미 풀려난 자유 메모리에 대한 시도를 감지 할 수 있습니다. 또는 할당 된 공간을 통해 부분적으로 포인터를 포인터 - 할당 된 공간과 별도로 저장하기 때문입니다. 비용은 디버깅 버전이 더 많은 공간을 차지하는 것입니다. 정말 좋은 할당자는 스택 추적 및 라인 번호를 기록하여 코드에서 할당이 어디에서 발생했는지 또는 첫 번째 자유가 발생한 위치를 알려줄 수 있습니다.

문제가 실제로 Segfault가 생성되는 위치에 있는지 확인하려면이 코드를 분리하여 디버깅해야합니다. (나는 그것이 아니라고 생각합니다).

이것은 다음을 의미합니다.

#1 : GDB가 올바른 줄 번호 정보를 얻을 수 있도록 -o0으로 코드를 컴파일하십시오.

#2 : 코드 의이 부분을 호출하는 단위 테스트를 작성하십시오.

내 생각에 별도로 사용하면 코드가 올바르게 작동한다는 것입니다. 그런 다음 버그의 원인을 찾을 때까지 같은 방식으로 다른 모듈을 테스트 할 수 있습니다.

다른 사람들이 제안한 것처럼 Valgrind를 사용하는 것도 아주 좋은 생각입니다.

코드는 문제가됩니다. Malloc이 NULL을 반환하면 코드 에서이 케이스가 올바르게 처리되지 않습니다. 당신은 단순히 기억이 실제로 없었을 때 당신을 위해 할당되었다고 가정합니다. 이것은 메모리 손상을 유발할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top