Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何从被调用方的角度检测内存是动态的还是静态的?_C++_C_Realloc_Static Memory Allocation - Fatal编程技术网

C++ 如何从被调用方的角度检测内存是动态的还是静态的?

C++ 如何从被调用方的角度检测内存是动态的还是静态的?,c++,c,realloc,static-memory-allocation,C++,C,Realloc,Static Memory Allocation,注意:当我在这里说“静态字符串”时,我指的是realloc无法处理的内存 您好,我已经编写了一个接受char*参数的过程,如果内存不能通过realloc重新定位/调整大小,我想创建一个副本。实际上,该过程是一个“沉重”的字符串处理器,因此不管字符串是否是静态的,如果不知道并复制该字符串,将来肯定会导致一些内存开销/处理问题 我尝试使用异常处理程序修改静态字符串,应用程序只是在没有任何通知的情况下退出。我退后一步,看着C,说:“我没有印象。”如果我听说过,那将是一个例外 我尝试使用异常处理程序对静

注意:当我在这里说“静态字符串”时,我指的是realloc无法处理的内存

您好,我已经编写了一个接受char*参数的过程,如果内存不能通过realloc重新定位/调整大小,我想创建一个副本。实际上,该过程是一个“沉重”的字符串处理器,因此不管字符串是否是静态的,如果不知道并复制该字符串,将来肯定会导致一些内存开销/处理问题

我尝试使用异常处理程序修改静态字符串,应用程序只是在没有任何通知的情况下退出。我退后一步,看着C,说:“我没有印象。”如果我听说过,那将是一个例外

我尝试使用异常处理程序对静态变量调用realloc。。。Glib报告说,它找不到一些私人信息的结构(我肯定)我不知道,显然是在程序中止,这意味着它不是一个例外,可以被捕获到龙JP/SETJMP或C++尝试,最后捕获。 我很确定一定有办法做到这一点。例如,动态内存很可能不位于静态内存附近的任何位置,因此如果有办法从地址泄露此信息。。。我们可能会玩宾果游戏


我不确定C/C++预处理器中是否有任何宏可以识别宏参数的源和类型,但如果没有,那就相当愚蠢了。宏汇编程序在这方面相当聪明。从缺乏健壮的错误处理来看,如果没有,我一点也不会感到惊讶。

任何解决方案都是特定于平台的,因此您可能需要指定正在运行的平台


至于为什么库在传递意外参数时应该调用
abort
,这往往比继续执行更安全。当然,这更烦人,但此时库知道调用它的代码处于无法恢复的状态。

您可以检测内存范围并进行一些指针比较。我已经在一些垃圾收集代码中这样做了,我需要知道指针是在堆栈、堆还是其他地方

如果您控制所有分配,您可以简单地根据从
malloc
calloc
realloc
发出的每个动态指针保持最小和最大界限。低于min或大于max的指针可能不在堆中,并且此
min
max
分隔区域不太可能与任何静态区域相交。如果您知道指针是静态的或来自malloc,并且该指针位于malloced存储的“边界框”之外,那么它必须是静态的


有一些“博物馆”机器,这种东西不起作用,而C标准没有给出使用关系运算符比较指向不同对象的指针的意义,除了完全相等或不相等之外。

C没有提供一种可移植的方法来区分静态分配的内存块和动态分配的内存块。您可以使用字符串指针和指示对象占用内存类型的标志构建自己的
struct
。在C++中,你可以用两个不同的构造函数来构造一个类,每个内存类型一个,让你的生活更容易。 至于中止您的程序,尝试释放或重新分配尚未动态分配的内存是未定义的行为,因此中止是一个公平的游戏

我已经编写了一个接受char*参数的过程,如果内存不能通过realloc重新定位/调整大小,我想创建一个副本

从根本上说,问题在于,您希望根据您正在操作的范围内不可用的信息进行内存管理。显然,在创建字符串时,您知道字符串是否在堆栈或堆上,但当您在函数中时,这些信息就会丢失。试图解决这一问题几乎是不可能的,而且肯定超出了标准

我尝试使用异常处理程序修改静态字符串,应用程序只是在没有任何通知的情况下退出。我退后一步,看着C,说:“我没有印象。”如果我听说过,那将是一个例外

如前所述,C没有例外。C++ >强> > <强>,但是C++标准委员会认为C++中C函数的行为不同,这将是一个噩梦。 我很确定一定有办法做到这一点

您可以让应用程序用您使用或创建的堆栈替换默认堆栈(因此,您知道中的地址范围),并检查地址是否在该范围内。但是,(1)这会给使用库的任何应用程序带来巨大的负担(当然,如果您使用库编写了唯一的应用程序,那么您可能愿意接受这一负担);(2)由于其他原因,无法检测出内存不能为“代码> ReLoC/ ED(使用<代码>静态<代码>),使用自定义分配器分配,在Windows上使用<代码> SysLoCu或HeAPOLLC/分配,使用<代码>新< <代码> > C++ >等。
相反,我建议您的函数使用一个函数指针,该指针指向用于重新分配内存的函数。如果函数指针为空,则复制内存。否则,您将调用该函数。

此处为原始海报。我忘了提到我有一个有效的解决方案来解决这个问题,它并不像我希望的那样强大。请不要心烦意乱,我感谢所有参与本次征求意见和答案的人。问题中的“过程”
本质上是可变的,需要的匿名
char*
参数不超过63个

它是什么:一个多字符串
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>

struct mkstr_record {
    size_t size;
    void *location;
};

// use the mkstr macro (in mkstr.h) to call this procedure.
// The first argument to mkstr MUST BE dynamically allocated. i.e.: by malloc(),
// or strdup(), unless that argument is the sole argument to mkstr. Calling mkstr()
// with a single argument is functionally equivalent to calling strdup() on the same
// address.
char *mkstr_(char *source, ...) {

    va_list args;

    size_t length = 0, item = 0;

    mkstr_record list[64]; /*

    maximum of 64 input vectors. this goes beyond reason!

    the result of this procedure is a string that CAN be
    concatenated by THIS procedure, or further more reallocated!

    We could probably count the arguments and initialize properly,
    but this function shouldn't be used to concatenate more than 20
    vectors per call. Unless you are just "asking for it".

    In any case, develop a workaround. Thank yourself later.

    */// Argument Range Will Not Be Validated. Caller Beware!!!

    va_start(args, source);

    char *thisArg = source;

        while (thisArg) {

            // don't validate list bounds here.
            // an if statement here is too costly for
            // for the meager benefit it can provide.

            length += list[item].size = strlen(thisArg);
            list[item].location = thisArg;
            thisArg = va_arg(args, char *);
            item++;

        }

    va_end(args);

    if (item == 1) return strdup(source);   // single argument: fail-safe

    length++;   // final zero terminator index.

    char *str = (char *) realloc(source, length);

    if (!str) return str;   // don't care. memory error. check your work.

    thisArg = (str + list[0].size);

    size_t count = item;

    for (item = 1; item < count; item++) {
        memcpy(thisArg, list[item].location, list[item].size);
        thisArg += list[item].size;
    }

    *(thisArg) = '\0';  // terminate the string.

    return str;

}
#ifndef MKSTR_H_
#define MKSTR_H_

extern char *mkstr_(char *string, ...);

// This macro ensures that the final argument to "mkstr" is null.
// arguments: const char *, ...
// limitation: 63 variable arguments max.
// stipulation: caller must free returned pointer.

#define mkstr(str, args...) mkstr_(str, ##args, NULL)
#define mkstrd(str, args...) mkstr_(strdup(str), ##args, NULL)

/* calling mkstr with more than 64 arguments should produce a segmentation fault
 * this is not a bug. it is intentional operation. The price of saving an in loop
 * error check comes at the cost of writing code that looks good and works great.
 *
 * If you need a babysitter, find a new function [period]
*/


#endif /* MKSTR_H_ */