为什么我的结构成员之一在尝试在函数中更改后未定义?我传递了结构作为参考

发布于 2025-01-12 15:32:34 字数 6229 浏览 2 评论 0原文

我正在为 search_tree() 函数编写代码,该函数用目录及其子目录中的所有文件填充 chArray 结构(动态字符数组)。

但是,我在使用 add_elements() 函数时遇到问题,该函数旨在将元素添加到 char 数组并相应地调整其大小。

尽管我将 chArray 变量作为函数的引用传递,但 array.size 成员在函数调用后未定义。

为什么会发生这种情况?

- 除此之外,我遇到了内存分配错误,但我几乎可以肯定其原因是 array.size 未定义的问题。

谢谢您的帮助!

PS 我已经在下面包含了我的整个代码,对于所有随机打印语句和奇怪的名称感到抱歉 - 这是我试图找出问题所在。

//
// Created by mario on 05/03/2022.
//

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <stddef.h>

#ifndef errno
extern int errno;
#endif

typedef struct {
    int init;
    int numEls;
    size_t size;
    char **elements;
} chArray;

void initArray(chArray *arr, int n, ...) {
    size_t c_size = 0;
    va_list ptr;
    arr = malloc(sizeof(chArray));
    *arr = (chArray) {.init = 1, .numEls = n, .size = sizeof(chArray), .elements = NULL};
    va_start(ptr, n);
    for (int i = 0; i < n; i++) {
        char *arg = va_arg(ptr, char*);
        c_size += strlen(arg) + 1;
        printf("%lu\n", c_size);
        if (i == 0) {
            arr->elements = (char **) malloc(strlen(arg) + 1);
        }
        else {
            arr->elements = realloc(arr->elements, arr->size + strlen(arg) + 1);
        }
        *(arr->elements + i) = arg;
    }
    va_end(ptr);
    arr->size = c_size + offsetof(chArray, elements);
    printf("%lu\n", arr->size);
}

void add_elements(chArray *arr, int n, ...) {
    va_list ptr;
    size_t new_size = arr->size;
    va_start(ptr, n);
    for (int i = 0; i < n; i++) {
        char *f_arg = va_arg(ptr, char *);
        new_size += strlen(f_arg) + 1;
    }
    va_end(ptr);
    arr = realloc(arr, new_size);
    va_start(ptr, n);
    for (int i = arr->numEls; i < n+arr->numEls; i++) {
        char *arg = va_arg(ptr, char*);
        arr->size += strlen(arg) + 1;
        if (i == 0) {
            arr->elements = (char **) malloc(strlen(arg) + 1);
        }
        else {
            arr->elements = realloc(arr->elements, arr->size + strlen(arg) + 1);
        }
        *(arr->elements + i) = arg;
    }
    va_end(ptr);
    arr->numEls += n;
}

int search_tree(char *tree, char *contains, chArray *ends) {
    struct dirent *entry;
    DIR *dir;
    struct stat buff;
    mode_t mode;

    char *not1 = ".";
    char *not2 = "..";

    unsigned long int tree_length = strlen(tree);
    char *last = tree + tree_length - 1;
#ifdef _WIN32
    if (last != '\\') {
        char *slash = "\\\0";
#else
    if (*last != '/') {
        char *slash = "/\0";
#endif
        if (*last == '\\') {
            char *temp = (char *) malloc(tree_length + 1);
            memset(temp, '\0', tree_length + 1);
            strncpy(temp, tree, tree_length - 1);
            tree = 0;
            tree = (char *) malloc(tree_length + 2);
            strcpy(tree, temp);
            strcat(tree, slash);
            free(temp);
        }
        else {
            char *temp = (char *) malloc(tree_length + 2);
            memset(temp, '\0', tree_length + 2);
            strcpy(temp, tree);
            tree = 0;
            tree = (char *) malloc(tree_length + 2);
            strcpy(tree, temp);
            strcat(tree, slash);
            free(temp);
        }
    }

    if (ends->init != 1) {
        printf("Once\n");
        initArray(ends, 0);
    }

    if ((dir = opendir(tree)) == NULL) {
        perror("An error occurred");
        fprintf(stderr, "Errno = %d", errno);
        return -1;
    }

    while ((entry = readdir(dir)) != NULL) {
        size_t length = strlen(tree) + strlen(entry->d_name) + 1;
        char *file_path = (char *) malloc(length);
        memset(file_path, '\0', length);
        strcpy(file_path, tree);
        strcat(file_path, entry->d_name);
        if (stat(file_path, &buff) != -1) {
            mode = buff.st_mode;
            if (S_ISDIR(mode) && (strcmp(entry->d_name, not1) != 0) && (strcmp(entry->d_name, not2) != 0)) {
                search_tree(file_path, contains, ends);
                for (int i = 0; i < ends->numEls; i++) {
                    printf("%s\n", *(ends->elements));
                }
            } else if (S_ISREG(mode)) {
                if (contains == NULL) {
                    add_elements(ends, 1, file_path);
                    for (int i = 0; i < ends->numEls; i++) {
                        printf("%s\n", *(ends->elements));
                    }
                }
                else {
                    if (strstr(file_path, contains) != NULL) {
                        add_elements(ends, 1, file_path);
                        for (int i = 0; i < ends->numEls; i++) {
                            printf("%s\n", *(ends->elements));
                        }
                    }
                }
            }
        }
        else {
            perror("An error occurred");
            fprintf(stderr, "Errno = %d", errno);
            return -1;
        }
    }
    closedir(dir);
    return 0;
}


int main(int argc, char *argv[]) {

    char *path = "/Users/mario/python";
    char *toComp = "python";

    // printf("%d\n", strcmp(strstr(path, "python"), toComp));

    chArray test;

    initArray(&test, 3, "Hello", "There", "Goodbye");
    printf("%lu\n", test.size);

    add_elements(&test, 10, "Soyez", "Jiduan", "Chifa3n", "Chifa4n", "Chifa5n", "Chif6an", "Chifan7", "Chifa8n", "Chifan9", "Chifan10");

    for (int i = 0; i < 6; i++) {
        printf("%s\n", *(test.elements + i));
    }
    chArray ends;
    char *tree = "/Users/mario/Desktop";
    search_tree(tree, ".py", &ends);
    printf("%lu\n", sizeof(ends));
    printf("%s\n%s\n", *ends.elements, *(ends.elements + 1));

    chArray *random = (chArray * ) malloc(48);
    printf("%lu\n", sizeof(*random));

    return 0;
}

输出:

36

4486016032

search_tree(4025,0x117c5a600)malloc:***对象0x7ff7b48d0838的错误:未分配正在重新分配的指针 search_tree(4025,0x117c5a600) malloc: *** 在 malloc_error_break 中设置断点进行调试

36 是从 add_elements() 函数中打印的数组大小,第二个数字相同,但在函数之后打印。

到底是怎么回事?

I am writing code for a search_tree() function which fills a chArray struct (dynamic char array) with all the files in a directory and its sub-directories.

However, I'm having problems with the add_elements() function, which is meant to add elements to the char array and adjust its size accordingly.

The array.size member is undefined after the function call, even though I passed the chArray variable as reference to the function.

Why is this happening?

-Apart from this I'm having memory allocation errors, but I'm nearly sure the reason for this is this issue with array.size being undefined.

Thank you for any help!!

P.S. I've included my entire code below, sorry for all the random print statements and weird names - this was me trying to figure out what was wrong.

//
// Created by mario on 05/03/2022.
//

#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <stddef.h>

#ifndef errno
extern int errno;
#endif

typedef struct {
    int init;
    int numEls;
    size_t size;
    char **elements;
} chArray;

void initArray(chArray *arr, int n, ...) {
    size_t c_size = 0;
    va_list ptr;
    arr = malloc(sizeof(chArray));
    *arr = (chArray) {.init = 1, .numEls = n, .size = sizeof(chArray), .elements = NULL};
    va_start(ptr, n);
    for (int i = 0; i < n; i++) {
        char *arg = va_arg(ptr, char*);
        c_size += strlen(arg) + 1;
        printf("%lu\n", c_size);
        if (i == 0) {
            arr->elements = (char **) malloc(strlen(arg) + 1);
        }
        else {
            arr->elements = realloc(arr->elements, arr->size + strlen(arg) + 1);
        }
        *(arr->elements + i) = arg;
    }
    va_end(ptr);
    arr->size = c_size + offsetof(chArray, elements);
    printf("%lu\n", arr->size);
}

void add_elements(chArray *arr, int n, ...) {
    va_list ptr;
    size_t new_size = arr->size;
    va_start(ptr, n);
    for (int i = 0; i < n; i++) {
        char *f_arg = va_arg(ptr, char *);
        new_size += strlen(f_arg) + 1;
    }
    va_end(ptr);
    arr = realloc(arr, new_size);
    va_start(ptr, n);
    for (int i = arr->numEls; i < n+arr->numEls; i++) {
        char *arg = va_arg(ptr, char*);
        arr->size += strlen(arg) + 1;
        if (i == 0) {
            arr->elements = (char **) malloc(strlen(arg) + 1);
        }
        else {
            arr->elements = realloc(arr->elements, arr->size + strlen(arg) + 1);
        }
        *(arr->elements + i) = arg;
    }
    va_end(ptr);
    arr->numEls += n;
}

int search_tree(char *tree, char *contains, chArray *ends) {
    struct dirent *entry;
    DIR *dir;
    struct stat buff;
    mode_t mode;

    char *not1 = ".";
    char *not2 = "..";

    unsigned long int tree_length = strlen(tree);
    char *last = tree + tree_length - 1;
#ifdef _WIN32
    if (last != '\\') {
        char *slash = "\\\0";
#else
    if (*last != '/') {
        char *slash = "/\0";
#endif
        if (*last == '\\') {
            char *temp = (char *) malloc(tree_length + 1);
            memset(temp, '\0', tree_length + 1);
            strncpy(temp, tree, tree_length - 1);
            tree = 0;
            tree = (char *) malloc(tree_length + 2);
            strcpy(tree, temp);
            strcat(tree, slash);
            free(temp);
        }
        else {
            char *temp = (char *) malloc(tree_length + 2);
            memset(temp, '\0', tree_length + 2);
            strcpy(temp, tree);
            tree = 0;
            tree = (char *) malloc(tree_length + 2);
            strcpy(tree, temp);
            strcat(tree, slash);
            free(temp);
        }
    }

    if (ends->init != 1) {
        printf("Once\n");
        initArray(ends, 0);
    }

    if ((dir = opendir(tree)) == NULL) {
        perror("An error occurred");
        fprintf(stderr, "Errno = %d", errno);
        return -1;
    }

    while ((entry = readdir(dir)) != NULL) {
        size_t length = strlen(tree) + strlen(entry->d_name) + 1;
        char *file_path = (char *) malloc(length);
        memset(file_path, '\0', length);
        strcpy(file_path, tree);
        strcat(file_path, entry->d_name);
        if (stat(file_path, &buff) != -1) {
            mode = buff.st_mode;
            if (S_ISDIR(mode) && (strcmp(entry->d_name, not1) != 0) && (strcmp(entry->d_name, not2) != 0)) {
                search_tree(file_path, contains, ends);
                for (int i = 0; i < ends->numEls; i++) {
                    printf("%s\n", *(ends->elements));
                }
            } else if (S_ISREG(mode)) {
                if (contains == NULL) {
                    add_elements(ends, 1, file_path);
                    for (int i = 0; i < ends->numEls; i++) {
                        printf("%s\n", *(ends->elements));
                    }
                }
                else {
                    if (strstr(file_path, contains) != NULL) {
                        add_elements(ends, 1, file_path);
                        for (int i = 0; i < ends->numEls; i++) {
                            printf("%s\n", *(ends->elements));
                        }
                    }
                }
            }
        }
        else {
            perror("An error occurred");
            fprintf(stderr, "Errno = %d", errno);
            return -1;
        }
    }
    closedir(dir);
    return 0;
}


int main(int argc, char *argv[]) {

    char *path = "/Users/mario/python";
    char *toComp = "python";

    // printf("%d\n", strcmp(strstr(path, "python"), toComp));

    chArray test;

    initArray(&test, 3, "Hello", "There", "Goodbye");
    printf("%lu\n", test.size);

    add_elements(&test, 10, "Soyez", "Jiduan", "Chifa3n", "Chifa4n", "Chifa5n", "Chif6an", "Chifan7", "Chifa8n", "Chifan9", "Chifan10");

    for (int i = 0; i < 6; i++) {
        printf("%s\n", *(test.elements + i));
    }
    chArray ends;
    char *tree = "/Users/mario/Desktop";
    search_tree(tree, ".py", &ends);
    printf("%lu\n", sizeof(ends));
    printf("%s\n%s\n", *ends.elements, *(ends.elements + 1));

    chArray *random = (chArray * ) malloc(48);
    printf("%lu\n", sizeof(*random));

    return 0;
}

Output:

36

4486016032

search_tree(4025,0x117c5a600) malloc: *** error for object 0x7ff7b48d0838: pointer being realloc'd was not allocated
search_tree(4025,0x117c5a600) malloc: *** set a breakpoint in malloc_error_break to debug

The 36 is the array's size printed from within the add_elements() function, and the second number is the same but printed just after the function.

What is going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文