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

情况比你想象的还要“糟糕”。比较仅针对指向同一对象(或仅指向超出的字节)的指针定义。因此,通常对于两个不同的对象(无论是静态分配为字符串文字还是动态分配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通常编译为仅对段内偏移进行比较。例如,如果p和都q指向它们(不同)段的开始,则它们的偏移量都为零,即使地址不同。因此p < qandp > q都是 false 和 yet 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 回答