2016-12-20 1 views
-3

C에서 varadic 함수를 로그 파일에 쓸 수 있지만 호출하자 마자 헤더에 세그먼트 오류가 발생합니다. 주 처리에서는 C - Variadic 함수가 컴파일되지만 세분화 오류가 발생합니다.

는 호출이 형식은 :

mqbLog("LOG_INFORMATION",0,0,"Connect",0,"","Parameter received"); 

및 기능은 이러한 방식으로 정의된다 :

void mqbLog(char *type, 
      int numContext, 
      double sec, 
      char *service, 
      int sizeData, 
      char *data, 
      char *fmt, 
      ... 
      ) 
{ 
    //write the log in the archive 
} 

그것은 OK 컴파일한다. 나는이 과정을 디버깅 할 때, mqbLog 함수에 대한 호출이 이루어집니다, 그것은 나에게 기능의 오픈 브래킷의 세그먼트 오류를 ​​준다, 그래서 함수 값에 대해 질문 할 수 있습니다

(gdb) p type 
$1 = 0x40205e "LOG_INFORMATION" 
(gdb) p numContext 
$2 = 0 
(gdb) p sec 
$3 = 0 
(gdb) p service 
$4 = 0x0 
(gdb) p sizeData 
$5 = 4202649 
(gdb) p data 
$6 = 0x0 

어떤 아이디어가 될 것입니다 감사하게 받았습니다.

+0

해당 기능을 구현할 때 버그가 있습니다. 먼저 ''주변의 해당 매뉴얼을 읽는 것이 좋습니다. –

+5

오류를 복제 할 충분한 코드를주십시오. –

+4

함수 선언은 어디에 있습니까? 호출은 프로토 타입의 범위에서'0'을'0.0'으로 암시 적으로 변환하는 것에 의존합니다. 함수가 호출되는 프로토 타입을 생략하면 본질적으로 정의되지 않은 동작입니다. variadic 함수를 호출하기 전에 반드시 범위에서 프로토 타입을 가져야합니다. 함수가 작동하지 않지만 함수를 구현 한 방법이 표시되지 않았습니다. 우리가 어떻게 디버깅 할 수 있다고 기대합니까? 당신이 잘못 할 수있는 일이 많이 있습니다. 그들 중 많은 수가 충돌로 이어질 수 있습니다. 충돌을 재현하는 MCVE ([MCVE])를 포함 시키십시오. –

답변

2

gdb 출력을 기반으로하여 호출자가 호출 한 함수의 프로토 타입이없는 것처럼 보입니다. @JonathanLeffler가 알아 차 렸듯이 0.0 대신 0을 작성 했으므로 호출 수신자가 double을 기다리고있는 곳의 정수가 전달됩니다. 포인터 값으로 판단


이는 인수에 할당 된 레지스터는 예컨대 존재에 의해 결정되는 시스템 V 호출 규칙으로 - 64 리눅스 아마도 세번째 정수 arg. (ABI/calling convention doc은 위키를 참조하십시오).

호출자와 수신자가 함수 서명에 대해 동의하지 않으면 어떤 arg가 어떤 레지스터에 들어 갔는지에 대해 동의하지 않을 것입니다. gdb가 호출자와 일치하지 않는 args를 표시하는 이유를 설명합니다. 그것은 그 암시 적 선언과 4 정수/포인터 인수 있기 때문에이 경우


호출자는 RCX에 "Connect" (주소)를 넣습니다.

발신자가 RDX에서 service의 값을 찾습니다. 호출자의 3 번째 정수/포인터 arg 때문입니다.

sec은 우연히 수신자에게 명백하게 0.0입니다. XMM0에 앉아있는 모든 것을 사용하고 있습니다. 또는 초기화되지 않은 스택 공간 호출자는 FP 인수가 레지스터에 전달되지 않았 음을 나타 내기 위해 AL=0을 설정 했으므로 (가변 함수에만 필요). 참고 al = fp 레지스터 args의 수에는 프로토 타입을 사용할 수있을 때 고정 된 비 가변 인수가 포함됩니다. 으로 컴파일하면 사용할 수있는 프로토 타입은 call 앞에 mov eax, 1이 포함됩니다. 프로토 타입 on the Godbolt compiler explorer을 포함하거나 포함하지 않고 컴파일하려면 source + asm을 참조하십시오.

다른 호출 규칙 (예 : 스택 args가있는 -m32)에서는 이러한 args가 스택에 전달되기 때문에 상황이 잘못 될 수 있지만 intdouble은 크기가 다릅니다. 암시 적 선언은 정의와 일치 할 것 FP의 인수에 대한 0.0 작성


.하지만 이것을하지 마십시오. 선언되지 않은 함수를 호출하는 것은 여전히 ​​끔찍한 생각입니다.. -Wall을 사용하면 코드가 나쁜 일을 할 때 컴파일러에서 알려줍니다.

함수가 여전히 충돌 할 수 있습니다. 표시되지 않은 코드에서 다른 버그를 알고 있습니까? 예를 들어, - 코드 충돌, 당신은 ASM 명령 살펴 봐야 할 때


는 나쁜이었다 포인터 파악에 추락 gdb에서 disas을 실행하십시오. 디버깅 도움말 질문 (레지스터 값과 함께)을 포함하여 직접 이해하지 못하더라도 많은 도움이 될 수 있습니다.

+0

감사합니다 피터! 나는 여러분이 나열한 변경을했고 완벽하게 작동합니다 (_double_ number (duh), 함수 선언). 미안 내가 전에 대답 할 수 없었다면, 어제는 혼란스러운 날이었다. D : –

관련 문제