3

リテラル文字列を割り当てられた文字列と区別しようとしているので、誤ってリテラル文字列をfree()しようとしないでください。これにより、セグメンテーション違反が発生します。

リテラル文字列をfree()しようとする理由には、次のように埋め込むことができるstrcat()ラッパーが含まれます。 strcatex("My name ", strcatex("is ", strMyName));

理由に関係なく、次のことを考慮してください。

void* mallocex(int intBytes) 
{
    void* newPtr;

    newPtr = malloc(intBytes);

    if(newPtr == 0)
        return 0;
    else if(newPtr > maxPointer)
        maxPointer = newPtr;

    return newPtr;
}

int SafeFree(void **ptr)
{
    if((unsigned long) ptr > (unsigned long) maxPointer) 
        return 0;
    else
        free(*ptr);

    return 1;
}

使用例:

char *newString;
newString = (char*) mallocex(12);

strcpy(newString, "Example one");

SafeFree(&newString);
SafeFree("Example two");

ヒープがどれだけ大きくなっても、これは常に機能しますか?

4

4 に答える 4

5

それに依存しないという保証はありません。
文字列リテラルには、読み取り専用の実装定義領域のどこかにメモリが割り当てられます。これが移植可能な方法で何になるかを知る方法はないため、それについて何も想定しないでください。

于 2012-04-20T04:41:25.693 に答える
1

状況はあなたが想像するよりも「悪い」です。比較は、同じオブジェクト(またはその先のバイトのみ)を指すポインターに対してのみ定義されます。したがって、一般に2つの異なるオブジェクト(文字列リテラルとして静的に割り当てられているか、動的に割り当てられているmallocかなど)の場合、一方が他方よりも小さいアドレスを持っているかどうかを尋ねることさえできません。ほとんどのプラットフォームでは、このような比較は機能しますが、厳密な意味でこれに依存することはできません。

于 2012-04-20T06:15:09.833 に答える
0

保証がないだけでなく、反対のことが当てはまるシステムはかなり一般的です。MacOS(私のラップトップ)では、例えば:

#include <stdio.h>
#include <stdlib.h>

void pr_addr(const char *name, void *addr) {
    printf("%s: %p\n", name, addr);
}

int main(void) {
    pr_addr("literal", "literal");
    pr_addr("heap", malloc(10));
    return 0;
}
$ cc -o foo -W -Wall -O foo.c
$ ./foo
literal: 0x1ff1
heap: 0x100160

したがって、ここでは、このrodataセクションはアリーナの開始点よりかなりmallocにあり、システムに表示されるものとは逆になっています。

一般に、派手なセグメンテーションまたは他の構造化されたポインタータイプを使用するシステムでは、隣接していないオブジェクト間の無意味な比較が発生します。のテストは、p < q多くの場合、セグメント内のオフセットのみの比較にコンパイルされます。たとえば、とが両方の(異なる)セグメントの開始pq指している場合、アドレスが異なっていても、両方のオフセットはゼロです。したがってp < q、とp > qは両方とも偽であり、まだp != qです。

于 2012-04-20T06:32:08.140 に答える
0

楽しみのために、私は他のリテラルのアドレスに基づいて推測しようとする試みを書きました。これは、潜在的なリテラルのアドレスを別の既知のリテラル、スタックアドレス、およびヒープアドレスと比較することによって機能します。潜在的なアドレスが他のアドレスよりもリテラルに近い場合、潜在的なアドレスはリテラルであると見なされます。実際にはおそらく信頼できません。これは単純化したバージョンです。

int is_literal_simplistic(char *s) {
    char *literal = "literal";
    char stack[] = "stack";
    char *heap = malloc(1);
    free(heap);
    unsigned long literal_delta = labs(literal - s);
    unsigned long stack_delta = labs(stack - s);
    unsigned long heap_delta = labs(heap - s);
    return (literal_delta < stack_delta && literal_delta < heap_delta);
}

これがより簡潔なバージョンです。おそらくもっと簡単かもしれません:

int is_literal(char *s) {
  char *heap = malloc(1);
  free(heap);
  unsigned long literal_delta = labs("literal" - s);
  unsigned long stack_delta = labs((char *)&s - s);
  unsigned long heap_delta = labs(heap - s);
  return (literal_delta < stack_delta && literal_delta < heap_delta);
}

完全に実行可能なテスト:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

//#define DEBUG

#ifdef DEBUG
void debug_literal(unsigned long literal,
                   unsigned long stack,
                   unsigned long heap,
                   unsigned long literal_delta,
                   unsigned long stack_delta,
                   unsigned long heap_delta) {
  printf("literal(%lx)  stack(%lx)  heap(%lx)\n", literal, stack, heap);
  printf("literal(%lu)  stack(%lu)  heap(%lu)\n", literal_delta, stack_delta, heap_delta);
  int answer = (literal_delta < stack_delta && literal_delta < heap_delta);
  printf("\t%s\n", answer ? "literal" : "other");
}
#else
void debug_literal(unsigned long literal,
                   unsigned long stack,
                   unsigned long heap,
                   unsigned long literal_delta,
                   unsigned long stack_delta,
                   unsigned long heap_delta) {
}
#endif

int is_literal_simplistic(char *s) {
    char *literal = "literal";
    char stack[] = "stack";
    char *heap = malloc(1);
    free(heap);
    unsigned long literal_delta = labs(literal - s);
    unsigned long stack_delta = labs(stack - s);
    unsigned long heap_delta = labs(heap - s);
    debug_literal((unsigned long)literal, (unsigned long)stack, (unsigned long)heap,
                  literal_delta, stack_delta, heap_delta);
    return (literal_delta < stack_delta && literal_delta < heap_delta);
}

int is_literal(char *s) {
  char *heap = malloc(1);
  free(heap);
  unsigned long literal_delta = labs("literal" - s);
  unsigned long stack_delta = labs((char *)&s - s);
  unsigned long heap_delta = labs(heap - s);
  debug_literal(0,0,0, literal_delta, stack_delta, heap_delta);
  return (literal_delta < stack_delta && literal_delta < heap_delta);
}

void test_literal_function(int(*liternal_fn)(char *)) {
  char *literal = "literal_test";
  char stack[] = "stack_test";
  char *heap = malloc(40);

  printf("\t%s\n", liternal_fn(literal) ? "literal" : "other");
  printf("\t%s\n", liternal_fn(stack) ? "literal" : "other");
  printf("\t%s\n", liternal_fn(heap) ? "literal" : "other");
  printf("\n");

  free(heap);
}

int main() {
  test_literal_function(is_literal_simplistic);
  test_literal_function(is_literal);

  return 0;
}
于 2016-11-30T21:18:47.203 に答える