2013-08-09 2 views
0

여기 내 문제입니다.포인터를 통해 char *에 액세스하면

나는 char *를 정기적으로 수정하는 클래스가 있습니다.

이 값을 읽을 수 있어야하는 또 다른 클래스가 있습니다. 그래서 char *를이 두 번째 클래스의 생성자에 전달하여 필요할 때 값을 확인할 수있게하려고합니다. 를 ClassA에서

: ClassB가에서

bool f_valid = false; // global 

m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall(&f_valid))); 

:

struct handleCall 
{ 
    bool* m_dataValid; 

    handleCall(bool* result) 
    { 
     // saving the pointer to the boolean that I want to change 
     m_dataValid = result; 
    } 

    method() 
    { 
     if (smth) 
     { 
      (*m_dataValid) = false; 
     } 
    } 
}; 

이 유형 부울입니다, 제가 다른 매개 변수가 구현의 예를 들어 보겠습니다 지금까지 그렇게 좋았습니다 - 이것이 효과가있는 것 같습니다. 두 클래스 모두이 부울을 변경하고 액세스 할 수 있습니다.

이제 char * (문자열을 사용할 수 없으므로 URL 주소와 같은 간단한 텍스트를 저장하는 가장 좋은 방법이라고 생각하십니까?)와 동일한 작업을 수행해야합니다. 그래서 여기

은 내가 쓴 것입니다 :

를 ClassA :

const char* f_url = "blah blah"; // global 

m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall2(&f_url))); 

ClassC :

struct handleCall2 
{ 
    char ** m_url; 

    handleCall2(char** url) 
    { 
     // saving the pointer to the char* 
     m_url= url; 
     std::cout << (*m_url) << std::endl; // prints out url fine 
    } 

    method() 
    { 
     std::cout << (*m_url) << std::endl; // by this time the value has been changed by ClassA, and I print out some rubbish - symbols, squares, etc. 
    } 
}; 

나는 문자열이 변경 되었기 때문에, 그 '주소도 변경 문제가되는 것 같아요 ? 나는 정말로 혼란스러워지고있다. 누군가가 나에게 무슨 일이 일어나고 있는지, 그리고 내가이 상황에서 무엇을해야 하는지를 말해 줄 수 있는가?

UPDATE :

문제가 나는 문자 * 수정 방법에 같은

가 보이는 : * 숯불에 문자열 값을 쓰는 다른 방법이

f_url = "new text"; // works fine 

f_url = fileUrl.c_str(); // doesn't work! I get rubbish in the value when I try to access it from ClassB 

strcpy(m_url, fileUrl.c_str()); // I also removed const from the variable and tried this - got a crash "access violation using location" :(

거기를?

+0

한 단어 : 참고 문헌. –

+1

아, 그리고 또 다른 것 : ['std :: string'] (http://en.cppreference.com/w/cpp/string/basic_string)은 원시 포인터보다 문자열을 다루는 것이 훨씬 낫습니다. –

+0

문자열은 컴파일하는 동안 파일의 .rdata 섹션에 할당됩니다. 파일을 수정하면 다른 데이터를 겹쳐 쓸 수 있습니다. 대신'std :: string'을 사용하십시오. –

답변

0
const char* f_url = "blah blah"; 

이 선언은 상수 문자열을 가리키는 포인터임을 나타냅니다. 그래서 당신은

strcpy(f_url, "hello world"); // copy to the preallocated place 

을 할 수 있지만

f_url = "hello world"; // do pointer assignment 

당신은 다음 상황이 할 수있는 경우 :

class ClassA { 
const char* f_url = "blah blah"; 
public: 
    void method() { 
     f_url = "hello world"; 
    } 
}; 

class ClassB { 
    char** m_url; 
public: 
    void print() { 
     cout << (* m_url); // m_url points to a string, allocated on the stack of ClassA::method() 
    } 
}; 

는 해당 문자열 "hello world"ClassA::method()의 스택에 할당 명심

을 . 그리고 해당 포인터는 ClassA::method()이 종료 될 때 더 이상 유효하지 않습니다. 내가 다음 제안 문제 해결 :

class ClassA { 
static const int max_path = 256; 
char f_url[max_path]; 
public: 
    void method() { 
     strcpy(f_url, "hello world"); 
    } 
}; 

class ClassB { 
    char** m_url; 
public: 
    void print() { 
     cout << (* m_url); 
    } 
}; 
+0

strcpy를 사용하지 않습니다 – user2199745

+0

그래서 사용하면 문제가 해결됩니다. – nikitoz

+0

오, 죄송합니다. 나는 당신의 메시지를 잘못 읽었습니다. – user2199745

0

을 나는 char * 접근에 문제가 표시되지 않습니다.

나는 샘플 코드를 작성했으며 저에게 도움이되었습니다.

void addHandler() { 
    const char* f_url = "blah blah"; 
    m_eventCatcher.addProxy(porting::shared_ptr<CallbackProxy>(new handleCall2(&f_url))); 
} 

void doStuff() { 
    addHandler(); 
    m_eventCatcher.callProxy(); 
} 

다음 문제가 f_url 밖으로이다 :이 같은이있는 경우

#include <iostream> 

class ClassThatPrints 
{ 
private: 
    const char **m_url; 

public: 
    ClassThatPrints(const char ** url) 
    { 
     m_url = url; 
     std::cout << (*m_url) << std::endl; 
    } 

    void PrintAfterModify(void) 
    { 
     std::cout << (*m_url) << std::endl; 
    } 
}; 

class ClassThatModifies 
{ 
private: 
    const char *m_charPointer; 
    ClassThatPrints *m_ClassThatPrints; 
public: 
    ClassThatModifies() 
    { 
     m_charPointer = "this is the original string"; 
     std::cout << "Printing before modification:" << std::endl; 
     m_ClassThatPrints = new ClassThatPrints(&m_charPointer); 
    } 

    ~ClassThatModifies() { 
     delete m_ClassThatPrints; 
    } 

    void ModifyStringAndPrint(void) 
    { 
     m_charPointer = "this is a modified string"; 
     std::cout << "Printing after modification:" << std::endl; 
     m_ClassThatPrints->PrintAfterModify(); 
    } 
}; 

int main() 
{ 
    ClassThatModifies objClassThatModifies; 
    objClassThatModifies.ModifyStringAndPrint(); 

} 
+0

맞습니다 -이 방법이 효과적입니다!바로 그때 모든 일을하고 있었고 그 문제는 다른 곳에서해야합니다 ... – user2199745

+0

너무 일찍 들어가서 고마워했습니다! :) – user2199745

+0

글쎄,이 코드는 질문에서 설명한 것과 다릅니다. 그는 hes가 포인터의 값을 수정한다고 말했고, "modifi method"에서 새로운 포인터를 만들었습니다. 큰 차이가 있습니다. modifing은 합법적 인 연산이며, 그 주소의 char 값을 수정합니다. 설명이 나를 위해 들리는 것처럼 보였습니다.) 절대적으로 부정확합니다. – dhein

0

: BTW 여기

는 참조 용 내 코드입니다 : 당신 될 수있다 다른 문제입니다 addHandler가 돌려주는 범위의 이 경우 부울 버전에도 문제가 발생했으며 (*m_dataValid) = false;은 다른 데이터를 덮어 씁니다.

+0

아니요, f_url과 bool은 범위를 벗어나지 않습니다. 모든 메소드 외부의 클래스 내부에서 정의됩니다. – user2199745

+0

그런 다음 _show_ that - 질문과 관련 있습니다. – Useless

+0

OK, 질문 수정, 잘하면 지금은 더 분명합니다. – user2199745

0
const char* f_url = "blah blah"; // global 

혹시이 라인을 오해할까요? const 한정자는 왼쪽에있는 키워드를 참조하여 배치 할 때 사용됩니다. 그것은 첫 번째 키워드로 받아 들일 수 있지만 그 다음에는 그 다음에 그 권리를 가리키는 것입니다.) 그래서 선언문에 : (const char) * f_url 그래서 const char에 대한 포인터입니다. 그리고 저는 추측하고 있습니다. (당신이 그 클래스의 값을 수정하는 방법이 무엇인지 모르겠습니다.) 당신이 스스로 얻었습니다. 왜 const char 값을 수정하면 쓰레기 출력으로 끝날 수 있죠? 난 당신이

char *const f_url = "blah blah"; 

로 선언 할 제안이

char (* const) f_url

그렇게 f_url가 수정 영역으로 지적되는 상수 주소 값이다. 하지만 "so blah blah"는 const 메모리 영역의 주소이므로 수정할 수 없습니다. ("blah blah") [count] = 아무거나; 어쨌든

그래서 당신은

char *const f_url = ThisIsACharArray[count]; 

을하고 f_url에 대한 문자열 일명 char 배열에 액세스해야합니다. 문자열이 실제로 f_url에 저장되지 않습니다

0

) 내가 생각하는 것처럼, 단지 선언 밖으로 CONST를 유지하고 자기에 의해 수정 메모리를 할당

또는 당신을위한 더 좋은 방법. 문자열은 어딘가에에 저장되고 f_url어딘가의 포인터에 대한 포인터입니다.

이 작업을 수행 할 경우 : 프로그램이 어딘가에서 문자열 "new text"이 포함됩니다 컴파일

f_url = "new text"; // works fine 

. f_url은 프로그램 중간에있는 일부 메모리를 가리킬 것입니다.

f_url = fileUrl.c_str(); // doesn't work! I get rubbish in the value when I try to access it from ClassB 

fileUrl


는 표준 : : 문자열입니다. fileUrl에는 c_str이 반환하는 문자열에 대한 자체 포인터가 있습니다. fileUrl이이 문자열을 관리해야하므로 fileUrl이 범위를 벗어나면 메모리가 다른 용도로 다시 사용될 수 있습니다. 메모리를 계속 사용하고 있는지는 알 수 없습니다.

// I assume you meant f_url here, not m_url 
    strcpy(f_url, fileUrl.c_str()); // I also removed const from the variable and tried this - got a crash "access violation using location" :(


는 이것이하는 일은 f_url 실제로 가리키는 내용에 따라 달라집니다. f_url이 프로그램 중간에있는 일부 메모리를 가리키는 경우 (예 : f_url = "blah blah";) 충돌이 발생합니다. 일반적으로 이것은 버그를 나타내므로 운영 체제에서는 버그를 허용하지 않습니다. 이 허용 된 경우

이 일어날 수 : 당신이

char *s = "hello world"; 
strcpy(s, "abracadabra"); 

printf("hello world"); // prints "abracadabra" 


당신이 문자열을 보유하는 메모리의 자신의 블록을 얻을 수있다해야 할 일은

, 그것을 무료로 할 때를 :

f_url = new char[fileUrl.length() + 1]; 
strcpy(f_url, fileUrl.c_str()); 

// when you don't need the string any more 
delete [] f_url; 

나 :

f_url = strdup(fileUrl.c_str()); 

// when you don't need the string any more 
free(f_url); 
,

또는 f_url은 메모리 관리를 담당하는 std::string입니다. (이것은 가장 쉬운 해결책입니다!)

관련 문제