[완료]대입연산에서 함수로부 리턴받은 주소값의 일부를 잘라 먹을 수가 있나요?

next의 이미지

static const char *str = "str";
 
const char *returnStr()
{
   return str;
}
 
int main()
{
   const char *result;
 
   result = returnStr();
}

위의 코드는 예인데요...
예를 들어 str의 주소가 0x0D502024 인데
result가 가지는 주소값은 0x0D50 가 될 수 있나요?

제가 이런 현상을 겪고 있는데 혹시 이런 현상을 보신적이 있으시거나 원인을 알고 계신분이 있으신가요?

chadr의 이미지

정상적인 경우라면 변하지 않아야합니다.
그런 경우는 어디선가 메모리를 잘못 참조하거나 하여 포인터값이 변경되는 경우입니다..

returnStr함수 내에서 뭔가 잘못된 연산때문에 저 함수라 리턴되면서 잘못된 주소가 들어가는것 같습니다.
저 함수 내부를 잘 살펴보세요.
-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

xylosper의 이미지

음..말을 잘못하신건진 모르겠지만, 적으신 그대로라면 당연히 다릅니다.
같은건 str과 result이지, str의 '주소'(즉 &str)와 result (혹은 &result)가 아니니까요...

grassman의 이미지

함수의 본체는 다른 파일에 있는 상황에서 정확한 prototype을 선언하지 않고 함수를 사용하는 경우에는 그런 현상이 발생할 수 있습니다.

보통 prototype이 선언되지 않은 함수의 리턴 값은 integer인 것으로 가정하므로
포인터 형의 크기가 integer 형의 크기보다 클 경우(예를 들어 32-bit 포인터에 16-bit integer를 사용하는 컴파일러)에는 포인터의 값이 손실되는 현상이 발생합니다. (경우에 따라서는 prototype이 없다고 경고가 발생할 수도 있습니다만 컴파일이 중단되지는 않습니다)

next의 이미지

잘라먹는 원인은 찾았습니다. 그런데 왜 이런건지 어떻게 고쳐야 할지는 좀 더 생각 해 봐야하겠네요.

원인은
예를 들자면 (환경은 little endian 입니다.)

a(0x04000002 번지)에 0x12345678 이라는 주소를 대입하라고 하면

이 녀석이

0x04000000 에 78
0x04000001 에 56
0x04000002 에 34
0x04000003 에 12
를 넣어 버리는 겁니다. 이러니 a가 가리키는 주소를 아무리 찍어 봐도 0x1234 이상은 안 나오는 겁니다. ㅜ.ㅡ

정상적이라면
0x04000002 에 78
0x04000003 에 56
0x04000004 에 34
0x04000005 에 12
가 되어야 한다고 생각 하는데 말이죠..

sixmen의 이미지

ARM 같은 환경에서는 충분히 가능성이 있는 얘기 같은데요..

int *ptr = 0x04000002;
*ptr = 0x12345678;

같이 4byte align이 안 된 메모리에 값을 읽거나 쓸 수가 없습니다.
그렇게 쓰려고 할 때 CPU 설정(?)에 따라 두가지 가능성이 있는 걸로 아는데
interrupt(?) 가 발생해서 실행이 중단되거나, 위에 쓰신 것처럼
0x04000000 이라는 주소에 쓰거나 입니다.

정 저렇게 align 안 된 메모리를 사용하고 싶으면
(char *)ptr = 0x78;
(char *)ptr + 1 = 0x56;

이렇게 한바이트씩이나 위의 경우라면 2byte align은 되어 있으니까 short로 2번에
나눠쓰거나 이런 식으로 해야 합니다.

저렇게 할 경우 PC에선 잘 돌아가기 때문에 저도 한번 문제가 일어난 적이 있었죠.

robo872의 이미지

main()함수에서 result는 4바이트 짜리인 예로 설명하신 것처럼 4의 배수가 아닌 주소에 변수를 할당하지는 않을 것 같습니다.
로컬 변수라 할지라도 저런 바운더리 규칙은 다 따를 것으로 보입니다.
환경에 대해 좀 더 자세히 알려주실 순 없나요?
컴파일러랑 CPU 종류 정도면 될 것 같네요.
그리고 저 소스로는 말씀하신 현상이 벌어질 것 같지 않습니다. 테스트 하신 코드가 저 코드 그대로인지도 확인해주심 좋겠네요.

next의 이미지

위의 코드는 단지 예를 든것이구요.
컴파일러나 cpu 등에 대한 소개 없이도 올린 질문에 대해서 답변 해 주신 분들께 정말 감사드립니다.

cpu는 arm core를 쓰고 있구요, 컴파일러는 ADS 입니다.

원인은 결국에는 찾았습니다.

구조체의 멤버 변수 중에 배열이 있는데 이 배열의 길이가 4byte align이 안되어 있어서 발생했습니다.


typedef struct {
...
char a[30];
char b[32];
...
}A;

과 같이 되어 있는 상태에서 b에는 4byte align 되어 있지 않은 주소가 할당 되면서 위에서 제가 말씀 드린 문제가 발생 했습니다.

그런데 이상한 것은 제가 알기로는 arm에서는 인위적으로 padding을 넣는것으로 알고 있습니다만 이 경우에는 padding 들어가지 않아 오히려 문제가 되는군요 ㅡ.ㅡ;;(구조체의 제일 큰 멤버 변수는 4byte 입니다.)

수정은 일단 배열의 크기를 4의 배수로 맞추어서 했습니다만, 근본적인 해결책이 아닌지라 구조체를 4byte align 하게끔 강제로 설정을 하는 방법을 찾고 있는 중입니다.(확인을 해 보니 강제로 pack시킨 곳은 없는 상태이고 다른 멤버 변수들은 모두 padding을 넣어서 4byte align이 되는데 유독 연속된 배열 두개는 align이 안되는 군요)

__attribute__((aligned(4)) 는 gcc에서만 동작 되는것 같고

#pragma pack(4) 는 적용해서 확인 해 봤는데 제대로 동작을 하지 않는것 같군요.

지금은 이래저래 alignment를 맞출 방법을 찾는 중입니다.

robo872의 이미지

ADS는 char과 같은 한 바이트는 바이트 단위, short같은 2 바이트는 2바이트 단위로 align 시킨다고 나오더군요.
char의 배열은 4의 배수로 길이를 안 맞추면 방법이 없더군요.
-zas 옵션이 있던데 이놈이 하는 게 뭔지 정확하게 모르겠더군요.
테스트 해볼려니 귀찮아서 혹 해보셨으면 결과 알려 주심 좋겠네요.

next의 이미지

-zas4로 테스트 해 봤는데 여전히 안되는군요.(-zas 옵션은 ARM document에는 deprecated 되었다는 동시에 차기 버전부터는 지원 안된다고 적혀 있는데 현 버전에서도 안되는 건지 아니면 이 다음 버전부터 안된다는 건지 모호 하네요.)

char나 short 이라서 그런건 아닌것 같고 char 배열이 연속되게 나타나는 경우에 일어나는 것 같습니다.

char, short 모두 테스트 해 봤는데 4 byte align이 되더군요.

말씀하신 대로 char 배열의 크기를 4의 배수로 맞추는 수 밖에 없겠네요.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.