【问题标题】:Getting valgrind error for uninitialised bytes when using write function使用写入功能时出现未初始化字节的 valgrind 错误
【发布时间】:2016-12-06 14:11:15
【问题描述】:

我的程序应该与 4 个子进程之间的管道进行通信。该程序可以运行,但是在使用 valgrind 检查程序时,我收到有关 char 缓冲区的错误,但程序结束并打印出正确的答案。这是错误:

终端命令:./prodajnaVerigaAnon 100

==12926== Syscall param write(buf) points to uninitialised byte(s)
==12926==    at 0x4F22710: __write_nocancel (syscall-template.S:81)
==12926==    by 0x400B4E: main (prodajnaVerigaAnon.c:45)
==12926==  Address 0xfff0007e4 is on thread 1's stack
==12926==  in frame #1, created by main (prodajnaVerigaAnon.c:9)
==12926== 
==12927== Syscall param write(buf) points to uninitialised byte(s)
==12927==    at 0x4F22710: __write_nocancel (syscall-template.S:81)
==12927==    by 0x400CCF: main (prodajnaVerigaAnon.c:68)
==12927==  Address 0xfff0007e4 is on thread 1's stack
==12927==  in frame #1, created by main (prodajnaVerigaAnon.c:9)
==12927== 
==12928== Syscall param write(buf) points to uninitialised byte(s)
==12928==    at 0x4F22710: __write_nocancel (syscall-template.S:81)
==12928==    by 0x400E58: main (prodajnaVerigaAnon.c:92)
==12928==  Address 0xfff0007e4 is on thread 1's stack
==12928==  in frame #1, created by main (prodajnaVerigaAnon.c:9)
==12928== 
156

这是程序的代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(int argc, char* argv[])
{
        int size = 80;
        int fd1[2];
        int fd2[2];
        int fd3[2];
        char readbuffer[size];

        if(argc > 1) {

            if(pipe(fd1) == -1) {
                perror("tezava pri odpiranju cevi 1");
                return -1;
            }
            if(pipe(fd2) == -1) {
                perror("tezava pri odpiranju cevi 2");
                return -1;
            }
            if(pipe(fd3) == -1) {
                perror("tezava pri odpiranju cevi 3");
                return -1;
            }

            for(int i=0;i<4;i++) {
                if(i==0) {
                    switch(fork()) {
                        case 0:
                            close(fd1[0]);

                            close(fd2[0]); 
                            close(fd2[1]);
                            close(fd3[0]);
                            close(fd3[1]);
                            for(int i=1;i<argc;i++) {
                                char init_price[size];
                                sprintf(init_price,"%d",atoi(argv[i]));
                                write(fd1[1], init_price, size);
                            }
                            close(fd1[1]);
                            _exit(0);

                    }
                }
                else if(i == 1) {
                    switch(fork()) {
                        case 0:
                            close(fd1[1]);

                            close(fd2[0]); 
                            close(fd3[0]);
                            close(fd3[1]);
                            for(int i=1;i<argc;i++) {
                                read(fd1[0], readbuffer, sizeof(readbuffer));
                                int tmp_price = atoi(readbuffer);
                                int fifth_of_price = tmp_price / 5;
                                tmp_price = tmp_price + fifth_of_price;
                                char buffer[size];
                                sprintf(buffer,"%d",tmp_price);
                                write(fd2[1],buffer,size);
                            }

                            close(fd2[1]);
                            close(fd1[0]);
                            _exit(0);
                    }
                }
                else if(i == 2) {
                    switch(fork()) {
                        case 0:
                            close(fd2[1]);

                            close(fd3[0]);
                            close(fd1[0]);
                            close(fd1[1]);

                            for(int i=1;i<argc;i++) {
                                read(fd2[0],readbuffer,sizeof(readbuffer));
                                int tmp_price = atoi(readbuffer);
                                int third_of_price = tmp_price * 0.3f;
                                tmp_price = tmp_price + third_of_price;
                                char buffer[size];
                                sprintf(buffer,"%d",tmp_price);
                                write(fd3[1],buffer,size);
                            }
                            close(fd3[1]);
                            close(fd2[0]);
                            _exit(0);
                    }
                }
                else if(i == 3) {
                    switch(fork()) {
                        case 0:
                            close(fd3[1]);

                            close(fd1[0]);
                            close(fd1[1]);
                            close(fd2[0]);
                            close(fd2[1]);
                            for(int i=1;i<argc;i++) {
                                read(fd3[0],readbuffer,sizeof(readbuffer));
                                printf("%s ",readbuffer);
                                fflush(stdout);
                            }
                            printf("\n");
                            close(fd3[0]);
                            _exit(0);

                    }
                }
            }

            close(fd1[0]); 
            close(fd1[1]);
            close(fd2[0]);
            close(fd2[1]);
            close(fd3[0]);
            close(fd3[1]);

            for(int i=0;i<4;i++) {
                wait(NULL);
            }


        }
        else {
            printf("Missing input arguments. Usage:\n./prodajnaVerigaAnon <price 1> <price 2> ... <price n>\n");
        }
        return(0);
}

有人可以帮我解决这个问题吗?
感谢您的时间和精力,

圆顶

【问题讨论】:

  • write(fd1[1], init_price, size) -> write(fd1[1], init_price, strlen(init_price))size 是缓冲区的大小(这里是 80),strlen(init_price) 是字符串的长度。如果您希望将字符串终止符写入文件,可能需要write(fd1[1], init_price, strlen(init_price) + 1)

标签: c linux memory pipe valgrind


【解决方案1】:

这个:

sprintf(init_price,"%d",atoi(argv[i]));
write(fd1[1], init_price, size);

错了,它将缓冲区的完整大小size 传递给write,但只有前几个字符会被sprintf() 写入。

解决办法是捕获返回值知道有多少:

const int len = sprintf(init_price, "%d", atoi(argv[i]));
write(fd1[1], init_price, (size_t) len);

如果您需要 0 终止符,请改为使用最后一个参数 (size_t) len + 1

【讨论】:

  • 或者,使用fdopen()围绕文件描述符打开一个流可能更方便,以便使用fprintf()而不是sprintf() + strlen() + write()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 2015-10-24
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
相关资源
最近更新 更多