【问题标题】:C program, "Uninitialized Value Error" on initialized int arrayC 程序,初始化 int 数组上的“未初始化值错误”
【发布时间】:2021-03-24 00:15:39
【问题描述】:

更新: 完全删除 print 语句(第 52 行),其他所有内容与下面的代码相同,这给了我 0 个错误。打印时(使用 philo[i])和此打印语句(为调试添加)中存在错误,但如果我在没有打印的情况下运行整个程序,则错误不存在。任何想法我做错了什么???

感谢您迄今为止的帮助。我已经根据目前收到的 cmets 进行了一些更改。

***** 原始(已编辑)问题 *****

我无法弄清楚为什么我会收到此错误,“未初始化的值是由堆栈分配创建的”。我从一个运行良好的完整程序开始,但给了我大量未初始化的值错误。通过排除所有函数并添加额外的打印语句,我已将问题追溯到几行代码。这段代码是用线程解决餐饮哲学家的问题(作业),所以不想发太多。我的代码现在是:

#include <all needed header files>

#define NUM_PHIL       5
#define MIN_EAT_TIME   10

pthread_t philosopher[NUM_PHIL];         // array to hold IDs for philosopher threads
pthread_mutex_t chopstick[NUM_PHIL];     // array to hold IDs for chopstick mutexes (locks)

// function definitions here: 
int philosopherFun(int *philo);
// All others have been bypassed at the time of my current problem

int main(int argc, char *argv[]) {
    
    int phil[NUM_PHIL];                  // Philosopher numbers ("names")
    
    for(int i = 0; i < NUM_PHIL; i++) {                 
        phil[i] = i + 1;
    }
    
    for(int i = 0; i < NUM_PHIL; i++) {                 
        // Print statement causes valgrind error to exist (as does calling a function using phil)
        printf("Value phil[%d] = %d\n", i, phil[i]);
    }
    
    // Initilize mutexes for chopsticks, report error as needed
    for(int i = 0; i < NUM_PHIL; i++) {
        if(pthread_mutex_init( stuff here) < 0) {
            // error reporting
            // print statement uses i
        }
    }

    for(int i = 0; i < NUM_PHIL; i++) {
        if(pthread_create(&philosopher[i], NULL, (void*) philosopherFun, (void*) &phil[i] ) != 0) {
            // error reporting
            // print statement uses phil[i]
        }
    }
    
    /* Code omitted as this is Homework */
    // Join threads created for philosophers (using pthread_join)
            // error reporting
            // print statement uses phil[i]

    // Destroy chopstick mutexes when done. (using pthread_mutex_destroy)
            // error reporting
            // print statement uses i

    printf("The philosophers have all finished eating and its time for bed. Goodnight...\n");
    return 0;
    
}

int philosopherFun(int *philo) {
    
    return 0;
}

程序输出:
值 phil[0] = 1
值 phil[1] = 2
值 phil[2] = 3
值 phil[3] = 4
值 phil[4] = 5
哲学家们都吃完了,该睡觉了。晚安...

我的 Valgrind 错误是:
==46556== 堆摘要:
==46556== 退出时使用:0 个块中的 0 个字节
==46556== 总堆使用量:0 次分配,0 次释放,0 字节分配
==46556==
==46556== 所有堆块都被释放——不可能有泄漏
==46556==
==46556== 错误摘要:来自 1 个上下文的 10 个错误(抑制:0 来自 0)
==46556==
==46556== 上下文 1 中的 10 个错误:
==46556== 条件跳转或移动取决于未初始化的值
==46556== 在 0x7FFF205A395F: ??? (在 /dev/ttys000 中)
==46556== 由 0x7FFF2046FFFA: ??? (在 /dev/ttys000 中)
==46556== 由 0x7FFF20478CF0: ??? (在 /dev/ttys000 中)
==46556== 由 0x7FFF2049D8B8: ??? (在 /dev/ttys000 中)
==46556== 由 0x7FFF20475EF5: ??? (在 /dev/ttys000 中)
==46556== 由 0x7FFF20474061: ??? (在 /dev/ttys000 中)
==46556== by 0x1000038CD: main (philo.c:52)
==46556== 未初始化的值是由堆栈分配创建的
==46556== 在 0x7FFF20475FDF: ??? (在 /dev/ttys000 中)
==46556==
==46556== 错误摘要:来自 1 个上下文的 10 个错误(抑制:0 来自 0)

第 52 行是我的打印语句: printf("值 phil[%d] = %d\n", i, phil[i]);

我认为这导致了 5 个错误(phil[0] - phil[4]),我在第 68 行的 pthread_create(包括这行代码)中调用了哲人Fun,再次导致 5 个错误(每个线程 1 个) .这个函数目前只在第一行返回,所以我的程序的其余部分都没有涉及(尽管我开始时有 50-250 个错误,具体取决于我的参数和我排除的函数)。

我觉得我的 int 数组 (int phil[]) 导致了问题,但它立即被初始化,所以我不确定这是怎么发生的。请帮忙!

谢谢, 克里斯汀

已编辑...从省略的代码中添加了一些 cmets - 线程被加入并且互斥体被破坏

我还尝试通过在我的 main 函数之外声明 int phil[NUM_PHIL] 来使其成为全局,但这并没有改变 Valgrind 返回的错误。定义 phil[5] = {1, 2, 3, 4, 5};作为一个全球性的也没有帮助。

【问题讨论】:

  • 您可以使用-g 编译标志添加调试符号。这将有助于 valgrind 等程序提供更多有用的输出。
  • 'int phil[NUM_PHIL];'当线程尝试访问它时,该数组是否仍然存在?
  • // Numbered 1 to i + 1 这样的评论在右边这样的评论比没用更糟糕。您花了很多精力将这些 cmets 格式化为在那里排成一行,而那是一个分散眼睛看代码的位置。不仅如此,注释只是重复了代码显然做了什么。写一个不添加任何信息的分散注意力的评论是浪费精力。
  • 这也很麻烦:(void*) philosopherFun 你为什么要把philsopherFun 转换成void *?使用强制转换粘贴错误是您做错了什么的标志。
  • 通过基本的编译修复,valgrind 错误不会出现在发布的代码中。请使用minimal reproducible example 更新您的问题。

标签: arrays c valgrind


【解决方案1】:

我相信这就是您的问题所在:

int phil[NUM_PHIL];

这里

if(pthread_create(&philosopher[i], NULL, (void*) philosopherFun, (void*) &phil[i] ) != 0) {
    more code ...
}

您正在引用堆栈分配的对象(您正在获取指向 philo 数组元素的指针)。当 main 函数返回时,内存将被删除,其他线程仍将持有垃圾。要确定这是问题所在,请将您的 philo 数组移动到全局范围,或者改为在堆上分配数组。

【讨论】:

  • 当main函数返回时...是的,但是当main()返回时程序退出。这不会导致printf() 在与访问数组的数组相同的范围内发出 Valgrind 错误。 将您的 philo 数组移动到全局范围,或者改为在堆上分配数组看到导致错误消失我不会感到惊讶,但是当前给出的错误详细信息是我'会认为这只会隐藏症状,并不能解决问题的根本原因。我怀疑根本原因在某种程度上是在省略的代码中。
  • 我明白你的意思,但这只是为了调试。我让他这样做,这样他就可以准确找出错误的来源
  • 将数组移出主函数,使其全局化,对 Valgrind 收到的错误没有影响
  • 无论如何philosopherFun() 从未真正取消引用该指针;它根本没有做任何事情。
  • @NateEldredge 它确实取消引用指针,这里: if(pthread_create(&philosopher[i], NULL, (void*)phthalFun, (void*) &phil[i] ) != 0) { the &phil[i] 正在获取数组元素之一的地址。据我所知,这就是问题的根源
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-21
  • 2011-07-10
  • 1970-01-01
  • 2012-11-10
  • 2014-03-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多