2017-04-07 8 views
1

내 프로그램의 변수 수가 다양하므로 execv을 새 경로로 만들어야합니다. 따라서 변경하지 않고 다른 변수에 argv[1]의 값을 변경하고 싶습니다. 그러나 그것은 나를시키지 않을 것이다.argv를 다른 변수에 복사하여 원래 변수를 변경하지 않고 복사하십시오.

char** arg_exec = malloc(argc * sizeof (char*)); 
int i; 
for(i=0;i <= argc-1; i++) 
    arg_exec[i] = strdup(argv[i]); 
arg_exec[argc] = NULL; 
if((pid = fork()) == 0){ 
    arg_exec[1] = strcat(directory , dir_info->d_name); //some variables with the current path and a name 
    execv(arg_exec[0], arg_exec); 
    printf("Error in process %d\n", getpid()); 
    return 1; 
} 

하지만이 줄을 실행 한 후 arg_exec[1] = strcat(directory , dir_info->d_name);이 변수는 argv [1]의 제 값을 변경하고, 내 프로그램이 실패 ..

는 그것은 execl(argv[0],strcat(directory , dir_info->d_name), ..., NULL);처럼 이후, execl으로 잘 작동하지만 난이 있기 때문에 변수를 실행하기위한 인자가 다양하다면, 그런 식으로 구현하는 것이 좋지 않을 것이다.

EDIT1가 : Edit2가 배열 의 끝에서 NULL을 추가 : 나는 find의 버전을하고 있어요, 그래서 strcat와 현재 디렉토리를 들여다 폴더를 추가합니다. 이 디렉토리의 initalization이다 char *directory = strcat(argv[1],"/");

+2

arg_exec [1] = strcat (directory, dir_info-> d_name);'? 그리고'디렉토리'는 어떻게 정의되고 iniatlised됩니까? – alk

+0

나는'find'의 버전을 만들고 있으므로, strcat는 현재 디렉토리에 찾을 폴더를 추가 할 것입니다. –

+0

"* Edit1 *"을 참조하십시오 : 할당 할 배열 요소의 수를 놓치 셨습니다. – alk

답변

2

char *directory = strcat(argv[1],"/"); 은 UB 인 할당을 넘어 수정하려고 시도합니다. @alk.

argv 자체를 UB로 수정할 수 있습니다. Is argv[n] writable?

둘 모두에 메모리를 할당하십시오.

참고 : 은 argv[argc]NULL이어야하므로 불충분합니다. 1 개 더 필요합니다. 알림 argcexecv()으로 전달되지 않습니다.


단계 1. 포인터 배열의 카피 argv[]

char **argv_new; 
size_t a_size = sizeof *argv_new * (argc + 1); // + 1 for the final NULL 
argv_new = malloc(a_size); 
memcpy(argv_new, argv, a_size); 

2 단계 형태 만들기 새로운 ARG [1]

int size = 1 + snprintf(NULL, 0, "%s/%s", argv[1], dir_info->d_name); 
argv_new[1] = malloc(size); 
snprintf(argv_new[1], size, "%s/%s", argv[1], dir_info->d_name); 

사용 그것

execv(arg_new[0], arg_new); 
free(argv_new[1]); 
free(argv_new); 

미정 : 추가 오류 검사 : argc > 1, malloc(), snprintf(), execv()

+0

최선의 경우'free()'에 대한 호출은 결코 실행되지 않을 것이다 ...-- 나는 그것들 앞에'perror()'를 추가 할 것이다. – alk

+1

@alk 어쩌면 \t 'argv'를 수정하는 것이 UB 일 수도 있습니다. Ref가 추가되었습니다. 레; 'perror()', OP는'printf ("프로세스 % d \ n", getpid()) 오류를 가지고있다; " – chux

+0

그건 나를 위해 일했다. –

2

도시 미스 같은 코드에 NULL -terminate 대상 포인터 배열 arg_exec.

이렇게하려면 하나 이상의 요소를 할당하고 명시 적으로 NULL으로 설정하십시오.


또한 코드 arg_exe의 요소 않는 제 할당은 메모리 어드레스가 손실 strdup() 의해 할당 같이, 메모리 누출이 발생 제의 결과를 덮어. argv 가정


main()를 통해 argv[1]의 경계를 넘어 쓰는 것을 argv[1]가이으로 가리키는에 그렇게 정의되지 않은 호출을 수행하여 "/"을 연결하기 위해 다음이 줄을

char *directory = strcat(argv[1],"/"); 

시도를 전달됩니다 행동. 그때부터 사고에서 일하는 것까지 모든 일이 일어날 수 있습니다.

BTW; directory포인터에서 char까지이므로 "문자열"과 같은 값을 저장하는 메모리는 제공하지 않습니다.

을 : 당신은 아마 대신

char *directory = strcat(argv[1],"/"); 

... 

    arg_exec[1] = strcat(directory , dir_info->d_name); 

의 원하는 것은

는 다음과 같이 (이 argv[1] 어떤 "기본"-directorie의 이름을 보유하고 argv_exe 할당하고 (수정) 코드에 따라 초기화되어 있다고 가정)입니다

{ 
    void * tmp = realloc(arg_exec[1], 
    strlen(arg_exec[1]) + strlen("/") + strlen(dir_info->d_name) + 1); 
    if (NULL == tmp) 
    { 
    perror("realloc() failed"); 
    exit(1); 
    } 

    arg_exec[1] = tmp; 
} 

strcat(arg_exec[1], "/"); 
strcat(arg_exec[1], dir_info->d_name); 
+0

이유는 모르겠지만 항상 realloc에 ​​오류가 있습니다. 어쨌든, 내 문제가 해결 된 또 다른 대답 –

2

directory 설정 방법을 표시하지 않았습니다. 나는 그것이이 경우

char *directory = argv[1]; 

같은 것이 있다고 의심, strcat와는 위치 directory가 가리키는 따라서 argv를한다 수정합니다.

+0

네, 그게 너무 문제였습니다. 그것을 정정했다 –