предупреждение valgrind : "invalid read of size..." , "Syscall param points to unaddressable byte(s)"

Имеется следующий код (C++):

 struct command
{
    vector<char*> argv;
    char* file_input;
    char* file_output;
 
    string leksema;
 
    command* follow_pipe;
 
 
    command() {
        file_input = file_output = 0;
        follow_pipe = 0;
    }
 
    ~command() {
        if (this->follow_pipe != nullptr )
            delete this->follow_pipe;
    }
};
 
void pipe_run (command* ptr) {
    pid_t pid, wpid;
    int pfd[2], input, status;
    bool first = true;
    while (ptr != nullptr ) {
        pipe(pfd);
        if (!(pid = fork())) {
            if (!first) {
                dup2(input, 0);
                close(input);
            }
            if ( ptr->follow_pipe != nullptr )
                dup2(pfd[1], 1);
            close(pfd[0]);
            close(pfd[1]);
            if ( ptr->file_input )
                change_in (ptr->file_input );
            if ( ptr->file_output )
                change_out (ptr->file_output );
            execvp( ptr->argv[0], &ptr->argv[0]);
            cerr<<"eexec_vp"<<'\n';
        }
        if (!first)
            close(input);
        close(pfd[1]);
        input = pfd[0];
        do {
            wpid = waitpid(pid, &status, WUNTRACED);
        } while (!WIFEXITED(status) && !WIFSIGNALED(status));
        first = false;
        ptr = ptr->follow_pipe;
    }
}

По факту, этот код эмуляция конвейера shell. Указатель ptr это фактически указатель на вершину связанного списка, ptr->follow_pipe -- указатель на следующую команду в конвейере. При запуске под valgring выдается предупреждение: "invalid read size of ", " Syscall param execve(argv[i]) points to unaddressable byte(s)"с ссылкой на строчку системного вызова execvp.

Объясните пожалуйста, на что же ругается valgrind и как это исправить.

update : добавил "перелив" vector<char*> -> char** -- проблему не решило:

struct command
{
    vector<char*> argv;
    char* file_input;
    char* file_output;

    string leksema;

    command* follow_pipe;


    command() {
        file_input = file_output = 0;
        follow_pipe = 0;
    }

    ~command() {
        if (this->follow_pipe != nullptr )
            delete this->follow_pipe;
    }
};

void pipe_run (command* ptr) {
    pid_t pid, wpid;
    int pfd[2], input, status;
    bool first = true;
    while (ptr != nullptr ) {
        pipe(pfd);
        if (!(pid = fork())) {
            if (!first) {
                dup2(input, 0);
                close(input);
            }
            if ( ptr->follow_pipe != nullptr )
                dup2(pfd[1], 1);
            close(pfd[0]);
            close(pfd[1]);
            if ( ptr->file_input )
                change_in (ptr->file_input );
            if ( ptr->file_output )
                change_out (ptr->file_output );
            if ( ptr->argv.size() > 0 ) {
                char** temp = new char*[ptr->argv.size()];
                for ( int i = 0; i < ptr->argv.size(); ++i )
                    temp[i] = ptr->argv[i];
                execvp(temp[0], temp);
            }
        }
        if (!first)
            close(input);
        close(pfd[1]);
        input = pfd[0];
        do {
            wpid = waitpid(pid, &status, WUNTRACED);
        } while (!WIFEXITED(status) && !WIFSIGNALED(status));
        first = false;
        ptr = ptr->follow_pipe;
    }
}

update2: добавил минимальный воспроизводимый пример (конвейер был замен на просто вызов функции, однако проблема все та же):

#include <iostream>
#include <unistd.h>
#include <string>
#include <cstring>
#include <sys/wait.h>
#include <fstream>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <cstdlib>
#include <vector>

using namespace std;

struct command
{
    vector<char*> argv;

    string leksema;

    ~command() {
    }
};

pid_t pid_run;

void command_run ( command*  pCmd) {
    execvp(pCmd->argv[0], &pCmd->argv[0]);
}

pair<string, int> extract_word (int idx, string & line) {
    int ptr = idx;
    string ans;
    while ( line[ptr] == ' ' || line[ptr] == '\t')
        ++ptr;
    while ( !(line[ptr] == ' ' || line[ptr] == '\t' || line[ptr] == '\n' || line[ptr] == '\000' ) ) {
        ans.push_back(line[ptr]);
        ++ptr;
    }
    return make_pair(ans, ptr+1 -idx);
}

void extract_command ( command* pCmd , int  idx, string & line) {
    vector<string> ARG;
    string file_in, file_out;

    pair<string, int> word;

    while ( idx < line.size() ) {
        switch ( line[idx]  ) {
        case ' ' : ++idx; break;
        case '\t' : ++idx; break;
        case '-' : word = extract_word(idx, line);
            ARG.push_back(word.first);
            idx +=word.second;
            break;
        default : word = extract_word(idx, line);
                 idx += word.second;
                 ARG.push_back(word.first);
        }
    }
    for (size_t i = 0; i < ARG.size(); i++)
       pCmd->argv.push_back((char *)ARG[i].c_str());
    pCmd->argv.push_back(nullptr);
    return;
}


int main () {
    string s ;
    getline(cin, s);
    command* temp = new command;
    extract_command (temp, 0,  s);
    command* temp_copy = temp;
    command_run ( temp );
    delete temp_copy;
    return 0;
}



Ответы (0 шт):