我将如何在我的C程序中设置内存、堆或堆栈使用的上限(或者,在原则上,但在本例中不是C++)?我在Windows 10上使用Visual。
我有一个完全工作的程序(嗯,库和一个小程序来运行基本测试并演示给我正在辅导的人),我想展示当内存分配失败时会发生什么。(我不仅仅是用愚蠢的大分配,因为它是链接列表,我想在这种情况下显示内存分配失败。)那么:我怎样才能限制我的程序允许使用的内存数量,我将在哪里这样做呢?我会在操作系统中做些什么来告诉它“我将要运行的这个应用程序只能使用X字节的RAM”(或者甚至告诉它限制堆或堆栈的大小),我会在编译器参数、链接器参数中做些什么吗?
我编写的代码有保护程序,防止非法访问内存,然后在malloc (或者,只在少数地方,calloc)返回NULL时崩溃!所以,不要担心非法的内存访问和其他东西,我对我正在做的事情有一个相当好的了解。
库标题singleLinkList.h如下所示:
#ifndef SINGLELINKEDLIST_H
#define SINGLELINKEDLIST_H
#ifndef KIND_OF_DATA
#define KIND_OF_DATA 3
#endif // !KIND_OF_DATA
#include <stdlib.h>
#include <stdio.h>
typedef long long LL_t;
#if KIND_OF_DATA == 1
typedef float data_t;
#define DATA_FORM "%f"
#elif KIND_OF_DATA == 2
typedef double data_t;
#define DATA_FORM "%lf"
#elif KIND_OF_DATA == 3
typedef LL_t data_t;
#define DATA_FORM "%lld"
#else
typedef int data_t;
#define DATA_FORM "%d"
#endif // KIND_OF_DATA == 1, 2, etc...
struct listStruct;
// equivalent to `list_t*` within the .c file
typedef struct listStruct* LS_p;
// equivalent to `const list_t* const` within the .c file
typedef const struct listStruct* const LS_cpc;
typedef struct listStruct* const LS_pc;
int showSizes(void);
size_t queryNodeSize(void);
// returns NULL on failure
LS_p newList(void);
// returns NULL on failure (in memory alloc, at any point), or if given the NULL pointer
LS_p mkListCopy(LS_cpc);
// copies one list into another; leaves the destination unmodified upon failure
//returns a value indicating success/type of failure; returns 0 on success,
// various `true` values on failure depending on type
// 1 indicates simple allocation failure
// -1 indicates that you gave the NULL pointer
int copyList(LS_pc dst, LS_cpc src);
//destroys (frees) the given singly-linked list (the list_t* given, and all the list of nodes whose head it holds)
void destroyList(LS_p);
// destroys the list pointed to, then sets it to NULL
//inline void strongDestroyList(LS_p* listP) {
inline void strongDestroyList(struct listStruct** listP) {
destroyList(*listP);
*listP = NULL;
}
// Takes a pointer to a list_t
// returns how many elements it has (runs in O(n) time)
// If you don't understand what `O(n) time` means, go look up "Big O Notation"
size_t len_list(LS_cpc);
//prints a list; returns characters printed
int print_list(LS_cpc);
// gets the data at the specified index of the list; sets the output parameter on failure
data_t indexToData(LS_pc, const size_t ind, int* const err);
// will write the data at ind to the output parameter
//returns a value indicating success/type of failure; returns 0 on success,
// various `true` values on failure depending on type
// 1 indicates simple allocation failure
// -1 indicates that you gave the NULL pointer
int copyToPointer(LS_pc, const size_t ind, data_t* const out);
// gets the data at the specified index and removes it from the list; sets output param on failure
data_t popFromInd(LS_pc, const size_t ind, int* const errFlag);
// pops the first item of the list; sets the output param on failure
data_t popFromTop(LS_pc, int* const errFlag);
//returns a value indicating success/type of failure; returns 0 on success,
// various `true` values on failure depending on type
// 1 indicates simple allocation failure
// -1 indicates that you gave the NULL pointer
int assignToIndex(LS_pc, const size_t ind, const data_t value);
//returns a value indicating success/type of failure; returns 0 on success,
// various `true` values on failure depending on type
// 1 indicates simple allocation failure
// 2 indicates inability to reach the specified index, because it's not that long.
// -1 indicates that you gave the NULL pointer
int insertAfterInd(LS_pc, const size_t ind, const data_t value);
//returns a value indicating success/type of failure; returns 0 on success,
// various `true` values on failure depending on type
// 1 indicates simple allocation failure
// -1 indicates that you gave the NULL pointer
int appendToEnd(LS_pc, const data_t value);
//returns a value indicating success/type of failure; returns 0 on success,
// various `true` values on failure depending on type
// 1 indicates simple allocation failure
// -1 indicates that you gave the NULL pointer
int insertAtStart(LS_pc list, const data_t value);
#endif // !SINGLELINKEDLIST_H运行演示/测试的main.c如下所示:
#ifdef __INTEL_COMPILER
#pragma warning disable 1786
#else
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS 1
#endif // _MSC_VER
#endif // __INTEL_COMPILER
#include "singleLinkList.h"
#include <stdio.h>
#include <string.h>
void cleanInputBuffer(void) {
char c;
do {
scanf("%c", &c);
} while (c != '\n');
}
void fill_avail_memory(void) {
size_t count = 0;
LS_p list = NULL;
size_t length;
data_t fin;
int err = 0;
const size_t nSize = queryNodeSize();
printf("nSize: %zu\n", nSize);
int last = -5;
printf("Do you wish to run the test that involves filling up available memory? "
"(only 'y' will be interpreted as an affirmative) => ");
char ans;
scanf("%c", &ans);
cleanInputBuffer();
if ((ans != 'y') && (ans != 'Y')) {
printf("Okay. Terminating function...\n");
return;
}
printf("Alright! Proceeding...\n");
list = newList();
if (list == NULL) {
printf("Wow, memory allocation failure already. Terminating...\n");
return;
}
print_list(list);
while (!(last = insertAtStart(list, (data_t)count))) {
++count;
}
length = len_list(list);
if (length < 5) {
print_list(list);
}
fin = indexToData(list, 0, &err);
strongDestroyList(&list);
printf("Last return value: %d\n", last);
if (!err) {
printf("Last inserted value: " DATA_FORM "\n", fin);
}
printf("Count, which was incremented on each successfull insert, reached: %zu\n", count);
printf("Length, which was calculated using len_list, was: %zu\n", length);
}
int main() {
printf("Hello world!\n");
showSizes();
LS_p list = newList();
print_list(list);
printf("Printing the list: "); print_list(list);
printf("Appending 5, inserting 1987 after it...\n");
appendToEnd(list, 5);
insertAfterInd(list, 0, 1987);
printf("Printing the list: "); print_list(list);
printf("Inserting 15 after index 0...\n");
insertAfterInd(list, 0, 15);
printf("Printing the list: "); print_list(list);
printf("Appending 45 to the list\n");
appendToEnd(list, 45);
printf("Printing the list: "); print_list(list);
//destroyList(list);
//list = NULL;
printf("Value of pointer-variable `list` is 0x%p\n", list);
printf("Destroying list...\n");
strongDestroyList(&list);
printf("Value of pointer-variable `list` is 0x%p\n", list);
printf("\n\n\n");
fill_avail_memory();
return 0;
}( __INTEL_COMPILER和_MSC_VER都是为了压制关于scanf使用的废话。
所以:
可以设置内存使用上限吗?如果可以,是否可以是堆对Stack-specific?
我将从终端编译(而不仅仅是“运行代码”,因为它是Visual项目),如下所示:
cl singleLinkList.c -c
cl main.c /Zp4 /link singleLinkList.obj任何帮助,或在哪里寻找的建议,将不胜感激!谢谢!更新:人们建议了职务对象。这看起来像是C++的事情。它能在普通的C上工作吗?(如果不是,那么也许就足够了,但这并不是我所期待的。)
发布于 2020-04-25 18:44:05
如果您想在用户/运行时级别执行此操作(并控制正在测试的代码),则可以实现您自己的safe_malloc()、safe_calloc()、safe_realloc()和safe_free(),它们将充当系统提供的对应方的前端,并适当地增加或减少numberOfBytesUsed计数器,但如果numberOfBytesUsed将大于固定的最大值,则会失败。
(请注意,这样做有点棘手,因为free()不包含无字节数的参数,所以您必须在safe_calloc()和朋友返回的分配缓冲区中“隐藏”该信息--通常是在调用代码请求的基础上再分配4个字节,将分配大小值放在分配的前4个字节中,然后在分配大小字段之后返回指向第一个字节的指针)
如果您无法控制正在测试的代码(即,该代码将直接调用malloc()和free(),并且无法重写代码来调用您的函数),那么您可能会遇到一些预处理前魔术(例如,您知道将包括的头文件中的#define calloc safe_calloc ),以欺骗测试代码做正确的事情。
至于限制使用堆栈空间的数量,我不知道有什么优雅的方法可以在代码级别强制执行。如果有一种使用编译器标志强制执行它的方法,您至少可以让程序在堆栈溢出条件下可靠崩溃,但这与受控/处理的失败并不完全相同。
发布于 2020-05-01 07:48:27
使用Visual,并且为了演示目的,您可以使用_DEBUG构建并用_CrtSetAllocHook连接到CRT内存管理中。这将允许程序监视内存分配,并根据需要触发故障。
https://stackoverflow.com/questions/61430428
复制相似问题