C Valgrind 堆栈跟踪失败,线性 malloc 结构数组

标签 c memory data-structures valgrind

这是我想要创建的一个 C 程序,它监视一组动态分配的结构(在程序初始化时创建)。这些结构目前具有基本要求(fd)。

实际上,

  1. 它初始化 N 个结构的内存
  2. 填写它们
  3. 在其中搜索匹配的文件描述符
  4. 在适当的地方进行匹配,如果太多则循环

问题在于 valgrind...我不知道我的指针、结构等做错了什么...

这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>

#define NO_ERROR 0
#define DEFAULT_ERROR -1

typedef struct dev_conn_state_s {
    int fd;
} dev_con_state_t;

int current_elements = 0;
int max_elements = 0;

int init_datastruct_commhandler(int size, dev_con_state_t ** conn_list);
dev_con_state_t *new_datastruct_commhandler_element(int fd, dev_con_state_t * conn_list);
dev_con_state_t *search_datastruct_commhandler_element(int fd, dev_con_state_t * conn_list);

dev_con_state_t *build_insert_element(dev_con_state_t * conn_list, int fd);
dev_con_state_t *build_search_element(dev_con_state_t * conn_list, int fd);

void set_max_conns(int max);
extern inline int get_max_conns(void);

/**
 * init_datastruct_commhandler(int size, dev_con_state_t ** conn_list)
 * 
 * @brief initializes large heap and buffer for each device to be tracked
 * @param size
 * @param conn_list
 * @return (-1) for error, 0 for success
 */
int init_datastruct_commhandler(int size, dev_con_state_t ** conn_list)
{
    printf("Init datahandler memory heap\n");

    // Quick param check
    if (size <= 0) {
        return DEFAULT_ERROR;
    }
    current_elements = 0;
    *conn_list = malloc(sizeof(dev_con_state_t) * size);

    // Check if malloc failed
    if (*conn_list == NULL) {
        printf("stack malloc failed\n");
        return DEFAULT_ERROR;
    }

    memset(*conn_list, 0, sizeof(dev_con_state_t) * size);

    printf("Completed datahandler memory heap\n");

    return NO_ERROR;
}

/**
 * build_insert_element(dev_con_state_t *conn_list, struct sockaddr_rc in_addr)
 * @brief Build a static element in the heap and insert
 * @param conn_list
 * @param fd
 * @param in_addr
 * @param conn if built
 */
dev_con_state_t *build_insert_element(dev_con_state_t * conn_list, int fd)
{
    //~ dev_con_state_t conn = { 0 };
    //~ printf("ob %p\n",fd);
    //~ conn.fd = fd;
    //conn.last_activity = time(NULL);
    printf("a %p %p\n",conn_list,&conn_list);

    return new_datastruct_commhandler_element(fd, conn_list);
}

/**
 * build_search_element(dev_con_state_t *conn_list)
 * @brief Build a static element in the heap and search
 * @param conn_list
 * @param fd
 * @param in_addr
 * @param conn if built
 */
dev_con_state_t *build_search_element(dev_con_state_t * conn_list, int fd)
{

    return search_datastruct_commhandler_element(fd, conn_list);
}

/**
 * new_datastruct_commhandler_element(dev_con_state_t * conn, dev_con_state_t * conn_list)
 * 
 * @brief Adds new datastruct to connection tracker heap
 * @param conn
 * @param conn_list
 * @return (-1) for error, 0 for success
 */
dev_con_state_t *new_datastruct_commhandler_element(int fd, dev_con_state_t * conn_list)
{

    //int size = sizeof(dev_con_state_t) * current_elements;
    printf("%p %p\n",conn_list,&conn_list);

    dev_con_state_t *tmp = conn_list + (sizeof(dev_con_state_t) * current_elements);

    int last_elements = current_elements;

    if (current_elements == (max_elements)) {
        tmp->fd = fd;
        current_elements = 0;
    } else {
        tmp->fd = fd;
        current_elements++;
    }

    return (dev_con_state_t *) conn_list + (sizeof(dev_con_state_t) * last_elements);
}

/**
 * search_datastruct_commhandler_element(dev_con_state_t * conn, dev_con_state_t * conn_list)
 * 
 * @brief Searches for datastruct in connection tracker heap
 * @note  USES FD (file descriptor) for NOW!
 * @param conn
 * @param conn_list
 * @return NULL for error, non-NULL for success (aka the element we were tracking)
 */
dev_con_state_t *search_datastruct_commhandler_element(int fd, dev_con_state_t * conn_list)
{
    int i = 0;
    dev_con_state_t *tmp = NULL;
    for (i = 0; i < get_max_conns(); i++) {
        tmp = (conn_list + (sizeof(dev_con_state_t) * i));

        if (tmp->fd == fd) {
            return ((dev_con_state_t *) conn_list + (sizeof(dev_con_state_t) * i));
        }

    }
    return (NULL);
}

/**
 * cleanup_connection_tracker(dev_con_state_t **conn_list)
 * 
 * @brief Cleanup connection tracker function
 * @param conn_list
 */
void cleanup_connection_tracker(dev_con_state_t ** conn_list)
{

    if (*conn_list != NULL) {
        free(*conn_list);
        *conn_list = NULL;
    }
}

/**
 * set_max_conns(int max)
 * @brief set max
 * @param max
 */
void set_max_conns(int max)
{
    max_elements = max;
}

/**
 * get_max_conns(void)
 * @brief get max
 * @return max
 */
inline int get_max_conns(void)
{
    return max_elements;
}

//#ifdef CODE_TEST
#define MAX_DEVS 8
int main(int argc, char **argv)
{
    int size = MAX_DEVS;
    dev_con_state_t *conn_list = NULL;

    printf("initial address: %p\n", conn_list);
    printf("initial address: %p\n", &conn_list);

    set_max_conns(size);

    if (init_datastruct_commhandler(size, &conn_list) < 0) {
        return (-1);
    }
    printf("init address: %p\n", conn_list);
    printf("init address: %p\n", &conn_list);

    dev_con_state_t conn_array[MAX_DEVS] = { 0 };

    dev_con_state_t *ptr = NULL;
    int i = 0;
    for (i = 0; i < get_max_conns(); i++) {
        conn_array[i].fd = i;
        //~ if ((ptr = new_datastruct_commhandler_element(conn_array[i].fd, conn_list)) == NULL) {
        //~ return (-1);
        //~ }
        /// test will error -> we looped around
        if ((ptr = build_insert_element(conn_list, conn_array[i].fd)) == NULL) {
            printf("error finding element\n");
        } else {
            printf("found: %d\n", ptr->fd);
        }

        printf("inserted: %d\n", ptr->fd);
    }

    if ((ptr = search_datastruct_commhandler_element(conn_array[5].fd, conn_list)) != NULL) {
        printf("found: %d\n", ptr->fd);
    } else {
        printf("NOT found: %d\n", conn_array[5].fd);
    }

    if ((ptr = search_datastruct_commhandler_element(conn_array[3].fd, conn_list)) != NULL) {
        printf("found: %d\n", ptr->fd);
    } else {
        printf("NOT found: %d\n", conn_array[3].fd);
    }

    /// Still visible out here?
    //~ dev_con_state_t *ptr2 =(&conn_list + sizeof(dev_con_state_t));
    //~ printf("test: %d\n", ptr2->fd);

    /// test for searching for last element
    if ((ptr = build_search_element(conn_list, conn_array[6].fd)) == NULL) {
        printf("error finding element\n");
    } else {
        printf("found: %d\n", ptr->fd);
    }

    /// test for finding a number that doesnt exist
    if ((ptr = build_search_element(conn_list, 9)) == NULL) {
        printf("error finding element\n");
    } else {
        printf("found: %d\n", ptr->fd);
    }

    if ((ptr = build_insert_element(conn_list, conn_array[6].fd)) == NULL) {
        printf("error finding element\n");
    } else {
        printf("inserted: %d\n", ptr->fd);
    }

    /// test will error -> we looped around
    if ((ptr = build_search_element(conn_list, conn_array[0].fd)) == NULL) {
        printf("error finding element\n");
    } else {
        printf("found: %d\n", ptr->fd);
    }

    cleanup_connection_tracker(&conn_list);

    printf("Done\n");
    return (0);
}

//#endif

我不知道是什么原因造成的...是我的 malloc 还是我执行算术的方式造成的?

 valgrind --tool=memcheck --leak-check=yes ./test
==27353== Memcheck, a memory error detector
==27353== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==27353== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==27353== Command: ./test
==27353== 
initial address: (nil)
initial address: 0xffefffdc8
Init datahandler memory heap
Completed datahandler memory heap
init address: 0x5202040
init address: 0xffefffdc8
a 0x5202040 0xffefffd78
0x5202040 0xffefffd40
found: 0
inserted: 0
a 0x5202040 0xffefffd78
0x5202040 0xffefffd40
found: 1
inserted: 1
a 0x5202040 0xffefffd78
0x5202040 0xffefffd40
==27353== Invalid write of size 4
==27353==    at 0x400784: new_datahub_commhandler_element (test.c:119)
==27353==    by 0x4006E9: build_insert_element (test.c:80)
==27353==    by 0x400968: main (test.c:213)
==27353==  Address 0x5202060 is 0 bytes after a block of size 32 alloc'd
==27353==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27353==    by 0x400656: init_datahub_commhandler (test.c:49)
==27353==    by 0x4008D3: main (test.c:197)
==27353== 
==27353== Invalid read of size 4
==27353==    at 0x400984: main (test.c:216)
==27353==  Address 0x5202060 is 0 bytes after a block of size 32 alloc'd
==27353==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27353==    by 0x400656: init_datahub_commhandler (test.c:49)
==27353==    by 0x4008D3: main (test.c:197)
==27353== 
found: 2
==27353== Invalid read of size 4
==27353==    at 0x40099B: main (test.c:219)
==27353==  Address 0x5202060 is 0 bytes after a block of size 32 alloc'd
==27353==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27353==    by 0x400656: init_datahub_commhandler (test.c:49)
==27353==    by 0x4008D3: main (test.c:197)
==27353== 
inserted: 2
a 0x5202040 0xffefffd78
0x5202040 0xffefffd40
found: 3
inserted: 3
a 0x5202040 0xffefffd78
0x5202040 0xffefffd40
found: 4
inserted: 4
a 0x5202040 0xffefffd78
0x5202040 0xffefffd40
found: 5
inserted: 5
a 0x5202040 0xffefffd78
0x5202040 0xffefffd40
found: 6
inserted: 6
a 0x5202040 0xffefffd78
0x5202040 0xffefffd40
found: 7
inserted: 7
==27353== Invalid read of size 4
==27353==    at 0x4007EA: search_datahub_commhandler_element (test.c:142)
==27353==    by 0x4009CC: main (test.c:222)
==27353==  Address 0x5202060 is 0 bytes after a block of size 32 alloc'd
==27353==    at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==27353==    by 0x400656: init_datahub_commhandler (test.c:49)
==27353==    by 0x4008D3: main (test.c:197)
==27353== 

valgrind: m_mallocfree.c:303 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed.
valgrind: Heap block lo/hi size mismatch: lo = 4, hi = 17179869184.
This is probably caused by your program erroneously writing past the
end of a heap block and corrupting heap metadata.  If you fix any
invalid writes reported by Memcheck, this assertion failure will
probably go away.  Please try that before reporting this as a bug.


host stacktrace:
==27353==    at 0x38083F98: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x380840B4: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x38084241: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x38091AEC: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x3807D653: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x3807BEE3: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x380800BA: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x3807B47A: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x380593E1: ??? (in /usr/lib/valgrind/memcheck-amd64-linux)
==27353==    by 0x802D490EB: ???
==27353==    by 0x802CA9F2F: ???
==27353==    by 0x80200831F: ???
==27353==    by 0x4009CC: main (test.c:222)

sched status:
  running_tid=1

Thread 1: status = VgTs_Runnable (lwpid 27353)
==27353==    at 0x4009DC: main (test.c:223)


Note: see also the FAQ in the source distribution.
It contains workarounds to several common problems.
In particular, if Valgrind aborted or crashed after
identifying problems in your program, there's a good chance
that fixing those problems will prevent Valgrind aborting or
crashing, especially if it happened in m_mallocfree.c.

If that doesn't help, please report this bug to: www.valgrind.org

In the bug report, send all the above text, the valgrind
version, and what OS and version you are using.  Thanks.

任何帮助都会很棒!我的头撞在键盘上......它似乎有效。正如给出的输出

    ./test 
initial address: (nil)
initial address: 0x7fff41386a68
Init datahandler memory heap
Completed datahandler memory heap
init address: 0x650010
init address: 0x7fff41386a68
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
found: 0
inserted: 0
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
found: 1
inserted: 1
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
found: 2
inserted: 2
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
found: 3
inserted: 3
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
found: 4
inserted: 4
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
found: 5
inserted: 5
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
found: 6
inserted: 6
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
found: 7
inserted: 7
found: 5
found: 3
found: 6
error finding element
a 0x650010 0x7fff41386a18
0x650010 0x7fff413869e0
inserted: 6
found: 0
Done

最佳答案

这是我最简单的解决方案的代码,由这里的一些史诗般的评论给出。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>

typedef struct mystruct_s {
    int fd;
    int a;
    int b;
} mystruct_t;

int current_elements = 0;
int max_elements = 0;

int init(int size, mystruct_t ** conn_list)
{
    if (size <= 0) {
        return (-1);
    }
    current_elements = 0;

    *conn_list = malloc(max_elements *sizeof(mystruct_t));

    if (*conn_list == NULL) {
        return (-1);
    }

    return (0);
}

void insert(int fd, mystruct_t ** conn_list, mystruct_t ** res)
{

    *res = NULL;

    if (current_elements == (max_elements)) {
        (*conn_list)[current_elements].fd = fd;
        (*conn_list)[current_elements].a = fd;
        (*conn_list)[current_elements].b = fd;
        *res = &(*conn_list)[current_elements];
        current_elements = 0;
    } else {
        (*conn_list)[current_elements].fd = fd;
        (*conn_list)[current_elements].a = fd;
        (*conn_list)[current_elements].b = fd;
        *res = &(*conn_list)[current_elements];
        current_elements++;
    }
}

int search(int fd, mystruct_t ** conn_list, mystruct_t ** res)
{
    int i = 0;
    if (*conn_list == NULL) {
        *res = NULL;        
        return (-1);
    }
    for (i = 0; i < max_elements; i++) {
        if ((*conn_list)[i].fd == fd) {
            *res = &(*conn_list)[i];
            return (1);
        }

    }
    *res = NULL;
    return (-1);
}

#define MAX_ELEMENTS 8
int main(int argc, char **argv)
{
    int size = MAX_ELEMENTS;
    mystruct_t conn_array[MAX_DEVS] = { 0 };
    mystruct_t *conn_list = NULL;

    max_elements = MAX_DEVS;

    if (init(size, &conn_list) < 0) {
        return (-1);
    }

    mystruct_t *ptr = NULL;
    int i = 0;
    for (i = 0; i < max_elements; i++) {
        conn_array[i].fd = i;
        insert(conn_array[i].fd, &conn_list, &ptr);
    }

    if ((search(conn_array[5].fd, &conn_list, &ptr)) > 0) {
        printf("Found: %d\n", ptr->fd);
    } else {
        printf("NOT found: %d\n", conn_array[5].fd);
    }

    if (conn_list != NULL) {
        free(conn_list);
    }
    return (0);
}

关于C Valgrind 堆栈跟踪失败,线性 malloc 结构数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39193936/

相关文章:

objective-c - 比较浮点值有多危险?

c - 同时运行两个共享内存的 C 程序,如何?

objective-c - 如果我依赖 Objective-C 中的垃圾收集,我是否需要 getter 和 setter

c - 数组与结构体的逻辑

c - 引用内存时,数据类型之间的真正区别是什么?

有效地将每个字 rune 件的 4 个字符序列压缩为 2 位

c - PECL 安装失败

ios - 如何在 iOS 中查找文本段范围

python - 在 Python 中构建 API 调用

VBA Excel - 在 VBA 中存储列表的方法?