2013-07-16 2 views
1

나는이 특별한 문제에 대해 머리털을 내고 조언을 원합니다. 이 같은 외부 어플리케이션에서 포인터 함수에 전달되는C++ string to char * array struct

struct MqlStr // MQL String Array 
{ 
int    len; 
char    *string; 
}; 

: I는 다음과 같은 구조체가 나는 문자열 값들을 생성하고 함수 내

MT4_EXPFUNC double __stdcall CheckExecutionRequests(MqlStr* RequestInfo) 

그런 난 에 대한 할당은 MqlStr 배열의 요소를 다양하게합니다. 미세 다음 작품 :

RequestInfo[1].string = "1"; 
RequestInfo[2].string = "2"; 

하지만 난 배열에 내 생성 된 문자열 값을 얻기 위해 strcpy를 사용할 때, 그것은 내가 복사 한 값으로 배열 전체를 덮어 씁니다. 예를 들어

string field1 = value.substr(Demark + 1, Demark2 - Demark - 1); 
strncpy(RequestInfo[1].string, field1.c_str(), field1.size()); 

string field2 = value.substr(Demark + 1, Demark2 - Demark - 1); 
strncpy(RequestInfo[2].string, field2.c_str(), field2.size()); 

1 = 필드 1의 경우와 FIELD2 = 2 다음 전체 RequestInfo를 [] 어레이는 2 (카피 마지막 값)

사람이 올바른 방향으로 날 포인트와 동일 할 것인가?

+0

try field1 = "a"및 field2 = "b", 내 생각에 전체 RequestInfo는 여전히 222가 될 것입니다 ... 22 –

+0

그래서이 바닥에 있습니다.문제는이 배열에 메모리를 할당하는 응용 프로그램이 제대로 수행하지 않는다는 것입니다. 그러한 모든 수정 시도로 인해 메모리가 손상됩니다. 이 응용 프로그램은 우리가 제어 할 수 없으므로 이에 대한 해결 방법을 찾아야합니다. 다른 사람이 검색하는 경우, 응용 프로그램은 Metatrader 4 (MT4) – Peter

답변

0
RequestInfo[1] = "1"; 

당신이 생각하는대로하지 않습니다. RequestInfo 단일 MqlStr 객체에의 포인터 인 경우 RequestInfo 적어도 2 개 요소 또는

RequestInfo->string = "1"; 

함유 MqlStr 객체 벡터 인 경우는 어느

RequestInfo[1].string = "1"; 

이다.

+0

입니다. 좋은 점은 제가 만든 오타였습니다 ... – Peter

0

RequestInfo 요소에 .string 포인터를위한 충분한 공간을 할당 했습니까? strncpy가 공간을 할당하지 않으므로 strdup를 사용하십시오.

+0

원본 참조 패드를 생성하는 외부 응용 프로그램이 충분한 공간을 확보하기 위해 256 자로 배열의 각 요소를 생성합니다. 그것에 할당 된 다른 것에 대해서. – Peter

0

메모리를 안전하게 관리해야하는 경우 std::string과 같은 표준 컨테이너를 사용하거나 내부 메모리를 할당하고 할당을 해제하는 방법을 사용하여 메모리를 안전하게 관리해야합니다.

#include <cstdlib> 
#include <iostream> 
#include <string.h> 
#include <sstream> 

struct MqlStr 
{ 
public: 
    int len; 
    char *string; 

    MqlStr() { init (); } 
    ~MqlStr() { dealloc(); } 
    void assign(std::string& str) { 
     dealloc(); 
     string = new char[str.length() + 1]; 
     strncpy(string, str.c_str(), str.length()); 
     string[str.length()] = 0; 
     len = str.length(); 
    } 
    void dealloc() { 
     if(string != 0) delete [] string; init(); 
    } 

private: 
    void init() { string = 0; len = 0; } 
     MqlStr(const MqlStr &); 
    void operator= (const MqlStr &); 
}; 

double CheckExecutionRequests(MqlStr* RequestInfo) 
{ 
    static int callCount = 0; 
    std::ostringstream stringstream; stringstream<<"callCount: "<<callCount++; 
    std::string field1 = stringstream.str(); 
    RequestInfo->assign(field1); 
    return 1.0; 
} 

int main(int argc, char** argv) 
{ 
    MqlStr s[5]; 

    std::cout<<"First call"<<std::endl; 
    for(unsigned i = 0; i < sizeof(s)/sizeof(s[0]); ++i) 
     CheckExecutionRequests(s + i); 

    for(unsigned i = 0; i < sizeof(s)/sizeof(s[0]); ++i) 
     std::cout<<"MqlStr["<<i<<"].string = "<<s[i].string<<std::endl; 

    std::cout<<"Second call"<<std::endl; 
    for(unsigned i = 0; i < sizeof(s)/sizeof(s[0]); ++i) 
     CheckExecutionRequests(s + i); 

    for(unsigned i = 0; i < sizeof(s)/sizeof(s[0]); ++i) 
     std::cout<<"MqlStr["<<i<<"].string = "<<s[i].string<<std::endl; 

    return EXIT_SUCCESS; 
} 

동일한 MqlStr 인스턴스와 CheckExecutionRequests의 두번째 실행 것 손상되지 메모리 : 여기서는

는 내부 메모리를 관리하는 간단한 클래스의 예이다. 코드 확장은 문자열 크기의 사전 할당 일 수 있으며 새 str.length> this.maxLength (문자열 크기와 다른 미리 할당 된 길이) 인 경우에만 assign 메서드에서 메모리를 다시 할당 할 수 있습니다. 복사 생성자와 할당 연산자는 현재 힙의 내부 메모리를 관리하는 동안 문제가 발생할 수 있으므로 제대로 작동하지 않습니다.

간단한 해결책은 다음과 같이 표준 컨테이너를 사용하여 구조체를 작성하는 것입니다 :

struct MqlStr 
{ 
public: 
    std::string string; 
} 

그리고 당신이 MqlStr 문자열로 필드를 얻을 문자열을 지정합니다.