【问题标题】:C: Passing one dimension of a 2D array results in segfaultC:传递二维数组的一维会导致段错误
【发布时间】:2013-07-24 13:07:48
【问题描述】:

自从我写完最后几行 C 以来已经有一段时间了,此时我在掌握 C 的窍门时遇到了问题。我想这可能是我犯的一个愚蠢的错误,但是在研究了一段时间后,我仍然无法弄清楚我做错了什么。所以这就是我的代码的样子:

int read_signal_from_file(const char* path, float* signal, SF_INFO * info) {
    SNDFILE *sndFile;
    sndFile = sf_open(path, SFM_READ, info);
    signal = malloc(info->frames * sizeof(float));
    long numFrames = sf_readf_float(sndFile, signal, info->frames);
    ...
}

int main(int argc, char *argv[]) {
    float** signals = malloc(NUM_FILES * sizeof(float*));
    float avg = 0.0;
    SF_INFO tmp_info;
    for(int i = 0; i < NUM_FILES; i++) {
        read_signal_from_file(INPUT_FILES[i], signals[i], &tmp_info);
        for(long j = 0; j < tmp_info.frames; j++) {
            printf("Sample no #%ld: %f\n", j, signals[i][j]);
        }
    }
}

read_signal_from_file() 内部,我可以毫无问题地访问分配的内存部分。但是,一旦我尝试从主函数的范围内访问它(例如,如上面的 printf() 示例中所示,我会得到损坏的结果,看起来可疑地像未初始化的内存或溢出。如果我尝试对该数据进行操作,(例如,通过调用vDSP_meanv(),应用程序会因段错误而崩溃。

【问题讨论】:

    标签: c multidimensional-array initialization segmentation-fault


    【解决方案1】:

    首先,你没有二维数组,你有一个指向指针的指针。

    然后,指针本身不指向任何东西,它们未初始化,因为您没有为它们分配内存 - 因此您的程序会调用未定义的行为。

    所以,要么在 for 循环中使用 malloc() 为它们分配内存,或者更好的是,使用真正的数组:

    float (*arr)[COLUMN_SIZE] = malloc(sizeof(*arr) * ROW_SIZE);
    

    【讨论】:

    • 感谢您的快速回答!问了这么愚蠢的问题我觉得很傻,但多亏了你,我不会再犯这个错误了:)
    • @maxPlauth 别担心,在 SO 上还有更糟糕的问题。就像,更糟糕的数量级(当 OP 甚至对他在做什么都没有一个最小的概念时)。你的不是其中之一。
    【解决方案2】:

    您正在分配指针数组,但您没有将它们设置为任何内容:

    float** signals = malloc(NUM_FILES * sizeof(float*));
    

    这意味着您在这里传递了一个未初始化的指针 (signals[i]):

    read_signal_from_file(INPUT_FILES[i], signals[i], &tmp_info)
    

    因为signals[i]是传值的,所以不会在函数调用中改变,所以read_signal_from_file返回后还是会未初始化。

    一个简单的改变是通过引用传递:

    int read_signal_from_file(const char* path, float* &signal, SF_INFO * info) { ... }
    

    【讨论】:

      【解决方案3】:

      (如前所述)您正在分配 signals 指针数组,但您没有分配此数组中的指针。当您在 read_signal_from_file 中分配 signal 时,您确实保留了内存,但您将指针分配给 local signal 变量。如果您想将分配的signal 分配给您的main 函数中的signals 数组,您应该将指针传递给该指针:

      read_signal_from_file(INPUT_FILES[i], &signals[i], &tmp_info);
      

      并更改您的 read_signal_from_file 函数以接受它:

      int read_signal_from_file(const char* path, float ** signal, SF_INFO * info) {
          // ...
          *signal = malloc(info->frames * sizeof(float));
          // ...
      

      【讨论】:

        【解决方案4】:

        您将float *signal 传递给read_signal_from_file() 并在那里重新分配signal,但这只会更改本地变量signal,而不是main() 中的signals[i]。 将read_signal_from_file()的签名改为

        int read_signal_from_file(const char* path, float** signal, SF_INFO * info)
        

        将您的 malloc() 更改为

        *signal = malloc(info->frames * sizeof(float));
        

        并传递signals+i 而不是signals[i]

        【讨论】:

          猜你喜欢
          • 2021-03-19
          • 1970-01-01
          • 2012-02-25
          • 1970-01-01
          • 1970-01-01
          • 2013-01-02
          • 1970-01-01
          • 2010-12-18
          • 1970-01-01
          相关资源
          最近更新 更多