我正在使用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, ¶ms);
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, ¶ms);
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
指向函数调用之前、内部和之后的位置。
请考虑将free
调用移动到记录函数内,或返回更新的数据指针,或按引用传递。其中任何一个都应该解决您的大部分(如果不是全部)问题。