предупреждение 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;
}