/* madplay.c */ #include<stdlib.h> #include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include <sys/ioctl.h> #include<fcntl.h> #include<unistd.h> #include<linux/soundcard.h> #define MAXLINE 4096 #define SIZE 16 /* 量化位数 */ #define CHANNELS 1 /* 声道数目 */ #define rate 8000 void madplay(FILE *de_fp) { int fd = open("/dev/dsp", O_WRONLY); if (fd==-1) { perror("open of /dev/dsp failed"); exit(1); } int arg; int status; /* 设置采样时的量化位数 */ arg = SIZE; status = ioctl(fd, SOUND_PCM_WRITE_BITS, &arg); if (status == -1) perror("SOUND_PCM_WRITE_BITS ioctl failed"); if (arg != SIZE) perror("unable to set sample size"); /* 设置采样时的声道数目 */ arg = CHANNELS; status = ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &arg); if (status == -1) perror("SOUND_PCM_WRITE_CHANNELS ioctl failed"); if (arg != CHANNELS) perror("unable to set number of channels"); /* 设置采样时的采样频率 */ arg = rate; status = ioctl(fd, SOUND_PCM_WRITE_RATE, &arg); if (status == -1) perror("SOUND_PCM_WRITE_WRITE ioctl failed"); unsigned char buf[MAXLINE]; printf("open of soundcard success\n");//test while(!feof(de_fp)){ printf("madplaying\n"); int status=fread(buf,sizeof(unsigned char),MAXLINE,de_fp);//de_fp文件数据读入buf if(status==0){ printf("status==0\n"); } else if (status != MAXLINE) perror("read wrong number of bytes"); write(fd,buf,status);//buf数据写入声卡 } close(fd); }优化代码
时间: 2023-05-27 07:03:11 浏览: 135
madplay.c 是一个程序文件的名称,它是一个用于播放MP3格式音频文件的开源软件。madplay.c 的实现基于mad音频解码器库,可以在 Linux、Unix、Windows 等操作系统中使用。其主要功能包括解码和播放 MP3 文件,支持循环、随机播放等操作。
相关问题
note: ‘sprintf’ output 34 or more bytes into a destination of size 1 sprintf(new_task,"madplay /home/%s/music/new_task.mp3",login);
`sprintf` 函数是一个用于格式化字符串并将其数据写入内存的 C 标准库函数。当你尝试使用 `sprintf(new_task, "madplay /home/%s/music/new_task.mp3", login)` 这行代码时,它会试图将登录名 (`login`) 插入到一个格式化的字符串中,以便创建播放新任务的命令。
然而,如果 `login` 的长度超过34个字符(包括空格和终止符),并且 `new_task` 变量只分配了1字节的空间去存储结果,这就会导致问题。因为`sprintf`会在内存中预留足够的空间来包含格式字符串、转换的数据以及终止符(如`\0`),所以当字符串过长而目标缓冲区太小时,可能会发生溢出,覆盖其他内存区域,造成未定义的行为。
为了避免这种情况,你应该确保 `new_task` 包含足够的空间来保存 `login` 的实际长度,或者调整 `sprintf` 的格式,限制插入内容的长度,例如添加`%.*s`来指定最大宽度:
```c
size_t len = strlen(login);
if (len <= sizeof(new_task) - 1) { // 确保有足够的空间减去终止符
sprintf(new_task, "madplay /home/%.*s/music/new_task.mp3", len, login);
} else {
printf("Error: Login name is too long for the target buffer.\n");
}
```
void play() { char *str=NULL; switch(CtrFlag) { case 0: { pid = fork(); if(pid==0) { str = strcat(cur_song->path,cur_song->name); //printf("\n%s\n",str); close(0);// //execlp("madplay","madplay",str,"-r","-q",NULL);//execlp会开辟一个新的线程覆盖掉子线程 system(“madplay str -r -q”); //execlp("play","play",str,"-r","-q",NULL);//execlp会开辟一个新的线程覆盖掉子线程 //execlp("mocp","mocp",str,"-r","-q",NULL);//execlp会开辟一个新的线程覆盖掉子线程 } CtrFlag = 2; } break; case 1: kill(pid,18);//对于主进程控制继续播放 CtrFlag = 2; break; case 2: { CtrFlag = 1; if(pid>0) { kill(pid,19);//主进程中暂停子进程 } } break; default: printf("play:"); } }这一段代码有什么问题,如何修改
这段代码可能存在以下问题:
1. 在第一个 case 中,使用了 strcat 函数将字符串拼接到了 cur_song->path 中,这可能会导致程序崩溃或不可预期的行为。应该使用 sprintf 函数或者手动将字符串拼接起来。
2. system 函数中传入的字符串常量应该使用双引号而不是中文引号。
3. 在第二个 case 中,kill 函数的第二个参数应该是 SIGCONT 而不是 18。
4. 在第四个 case 中,缺少了错误信息的输出。
修改后的代码如下:
```
void play() {
char str[1024];
switch(CtrFlag) {
case 0: {
pid = fork();
if(pid == 0) {
sprintf(str, "%s%s", cur_song->path, cur_song->name);
close(0);
execlp("madplay", "madplay", str, "-r", "-q", NULL);
perror("madplay");
exit(1);
}
CtrFlag = 2;
break;
}
case 1:
kill(pid, SIGCONT);
CtrFlag = 2;
break;
case 2: {
CtrFlag = 1;
if(pid > 0) {
kill(pid, SIGSTOP);
}
break;
}
default:
printf("play: unknown CtrFlag\n");
}
}
```
阅读全文