使用C语言execvp传递程序参数失败,参数无法正确转发
问题根源分析与解决方案
这问题我一眼就戳中要害了——你犯了C语言指针使用的经典错误:所有array1的元素都指向同一个内存块buf1!
为什么会出现3 3 3的结果?
看你这段核心代码:
char buf1[50]; char *array1[4]; for (int i = 0; i < 3; i++){ bytes_recieved1 = recv(clientfd, buf1, 50, 0); array1[i] = buf1; // 关键错误在这里! printf("%s = buffer\n", buf1); }
每次循环里,recv都会把新参数写入buf1这个固定的栈内存,而你只是把buf1的起始地址赋值给array1[i]。循环结束后,buf1里存的是最后一次接收的内容"3",array1[0]、array1[1]、array1[2]三个指针全指向同一块内存,自然传递给目标程序后,所有参数都显示成最后一个值。
而你手动赋值array1[0] = "1";时,每个字符串字面量都存在独立的只读内存区域,指针指向不同地址,所以能正常工作。
修正方案
你需要为每个参数分配独立的内存空间,把buf1的内容复制进去,而不是直接复用同一个缓冲区的地址。同时还要注意execvp的要求:参数数组必须以NULL结尾。
这里给你修改后的代码,顺便修复了其他潜在问题:
// 先修正buf的大小,避免recv时缓冲区溢出 char buf[5000]; int bytes_recieved = recv(clientfd, buf, sizeof(buf)-1, 0); if (bytes_recieved == -1) { perror("recv program name failed"); return 1; } buf[bytes_recieved] = '\0'; char buf1[50]; char *array1[4]; for (int i = 0; i < 3; i++){ int bytes_recieved1 = recv(clientfd, buf1, sizeof(buf1)-1, 0); if (bytes_recieved1 == -1) { perror("recv argument failed"); // 错误时要释放已分配的内存,避免泄漏 for (int j = 0; j < i; j++) { free(array1[j]); } return 1; } buf1[bytes_recieved1] = '\0'; // 正确设置字符串终止符 // 为当前参数分配独立内存并复制内容 array1[i] = malloc(strlen(buf1) + 1); if (array1[i] == NULL) { perror("malloc failed"); for (int j = 0; j < i; j++) { free(array1[j]); } return 1; } strcpy(array1[i], buf1); printf("%s = buffer\n", array1[i]); } array1[3] = NULL; // execvp要求参数数组必须以NULL结尾 printTime(); fprintf(stdout,"attempting to execute program: %s\n", buf); if(execvp(buf, array1) == -1) { perror("execvp failed"); // 释放内存后再返回错误 for (int i = 0; i < 3; i++) { free(array1[i]); } return 1; }
额外注意事项
- 错误处理:一定要检查
recv、malloc的返回值,避免程序崩溃或内存泄漏; - 粘包问题:如果客户端和服务端没有明确的参数分隔协议(比如每个参数固定长度、先传参数个数),
recv可能会出现多个参数粘在一起的情况,需要补充协议逻辑; - 缓冲区大小:如果参数长度可能超过50,要调整
buf1的大小,或者改成动态分配内存接收参数。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

