【问题标题】:Segmentation fault possible from code within false conditional block?错误条件块中的代码可能导致分段错误?
【发布时间】:2018-08-11 19:23:51
【问题描述】:

我正在使用 ALSA API 与 Linux 中的 USB 音频编解码器交互。我的代码检查 -r-p 标志,并分别录制或播放音频:

 int main(int argc, char** argv){
   if(argc > 1){
     if(strcmp("-p", argv[1]) == 0){
       // Create data buffer, choose sampling rate
       char* playback_data;
       unsigned int sampling_rate = 44100;


       // Declare handle and params structure
       snd_pcm_t* handle;
       snd_pcm_hw_params_t* params;

       // Initiate and configure sound device
       init_playback_device(&handle, &params);
       config_playback_device(handle, params, sampling_rate);

       // Playback
       printf("playing...\n");
       playback(handle, params, playback_data, "test.raw", 3);

       // Close
       snd_pcm_hw_params_free(params);
       snd_pcm_close(handle);
       free(playback_data);

     } else if(strcmp("-r", argv[1]) == 0){
       // Create data buffer, choose sampling rate
       char* record_data;
       unsigned int sampling_rate = 44100;

       // Declare handle and params structure
       snd_pcm_t* handle;
       snd_pcm_hw_params_t* params;

       // Initiate and configure sound device
       init_recording_device(&handle, &params);
       config_recording_device(handle, params, sampling_rate);

       // Record
       printf("recording...\n");
       record(handle, params, record_data, "test.raw", 3);

       // Close
       snd_pcm_hw_params_free(params);
       snd_pcm_close(handle);
       free(record_data);
     }
   }
   return 0; 
 }

每当我运行./audio -r 时,都会遇到分段错误。奇怪的是,当我在第一个 if 语句(-p 标志)中注释掉代码时,我没有遇到分段错误。我不明白为什么首先注释掉没有运行的代码(由于错误的条件)会产生段错误。使用 valgrind 会出现以下问题:

==22959== Conditional jump or move depends on uninitialised value(s)
==22959==    at 0x4848BAC: free (vg_replace_malloc.c:530)
==22959==    by 0x10DA7: main (audio.c:59)
==22959==  Uninitialised value was created by a stack allocation
==22959==    at 0x10C5C: main (audio.c:14)
==22959==
==22959== Invalid free() / delete / delete[] / realloc()
==22959==    at 0x4848BFC: free (vg_replace_malloc.c:530)
==22959==    by 0x10DA7: main (audio.c:59)
==22959==  Address 0x10b2c is in the Text segment of /home/pi/audio/audio
==22959==    at 0x10B2C: ??? (in /home/pi/audio/audio)

它不喜欢free(record_data) 行,因为它认为record_data 未初始化,但是在我的record 函数中,我处理了这个:

 void record(snd_pcm_t* handle, snd_pcm_hw_params_t* params, char* data_buffer, char file[], int duration){
   // Open file
   FILE* audio_file;
   audio_file = fopen(file, "w+");

   data_buffer = (char*) malloc(NUM_FRAMES * 4);

   int i;
   for(i = 0; i < (duration*10); i++){
     snd_pcm_readi(handle, data_buffer, NUM_FRAMES);
     fwrite(data_buffer, sizeof(char), NUM_FRAMES * 4 , audio_file);
   }

   fclose(audio_file);
 }

指向record_data 的指针作为参数data_buffer 传递。有人知道出了什么问题吗?

编辑:

解决方案是传递record_data 的指针,因为playback 函数发出了一个指向局部变量的指针:

 void record(snd_pcm_t* handle, snd_pcm_hw_params_t* params, char** data_buffer, char file[], int duration){
   // Open file
   FILE* audio_file;
   audio_file = fopen(file, "w+");
   *data_buffer = (char*) malloc(NUM_FRAMES * 4);
   int i;
   for(i = 0; i < (duration*10); i++){
      snd_pcm_readi(handle, *data_buffer, NUM_FRAMES);
     fwrite(*data_buffer, sizeof(char), NUM_FRAMES * 4 , audio_file);
   }
   fclose(audio_file);
 }

我仍然很好奇为什么注释掉第一个条件块中的代码会消除错误。仍然不确定为什么会这样。

【问题讨论】:

  • record_data没有初始化,你不知道它指向哪里,所以以record_data的值作为参数调用record()肯定是错误的

标签: c memory segmentation-fault


【解决方案1】:

首先,Valgrind 是对的。您正在使用未初始化的指针。您需要先分配内存,然后再写入该位置。当您在函数内部分配内存时,您只会覆盖指针的 local 值,而不会将该新指针返回给周围的代码。

比较record_data 指向函数调用之前、内部和之后的位置。

考虑将您的free 调用移动到您的记录函数中,或者返回更新后的数据指针,或者通过引用传递。其中任何一个都应该可以解决您的大部分(如果不是全部)问题。

【讨论】:

    猜你喜欢
    • 2012-01-15
    • 2017-08-18
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 2011-02-22
    • 1970-01-01
    • 2012-08-14
    相关资源
    最近更新 更多