我从下面的程序中得到了一个分段错误。
#include <stdio.h>
#include <string.h>
void removeProcess(int*, int);
void removeProcessN(char**, int, int);
void main() {
int numPro = 0, quanTime = 0, contTime = 0, i, elemNum, time = 0;
//Supply variables with user input
printf("Enter number of processes: ");
scanf("%d", &numPro);
printf("Enter context switch time: ");
scanf("%d", &contTime);
printf("Enter quantum of time: ");
scanf("%d", &quanTime);
//Create array of number of process time
int proTime[numPro];
//Create string array for better output
char *proNames[numPro];
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
sprintf(proNames[i], "p%d", i);
}
elemNum = 0;
//While a process remains active
while (numPro != 0) {
//Retrieves the element being worked with
elemNum = elemNum % numPro;
//Describe process working with
printf("Executing process %s\nStart time = %d\n", proNames[elemNum], time);
proTime[elemNum] -= quanTime;
//If process time complete, remove process
if (proTime[elemNum] <= 0){
removeProcess(proTime, elemNum);
removeProcessN(proNames, elemNum, numPro);
--numPro;
}
//Add amount of time with context time
time = time + quanTime + contTime;
elemNum++;
}
}
/**
*@param *array pointer to an array of integers
*@param elem int of the element to remove
* Removes an element 'elem' from the supplied integer array.
*/
void removeProcessN(char **array, int numElem, int elem) {
char *temparray[numElem - 1];
//Copy array to temparray except for elem to remove
int i;
for (i = 0; i < elem; i++) {
if (i == numElem) {
continue;
} else {
temparray[i] = array[i];
}
}
//End by setting the pointer of array to the temparray
array = temparray;
}
/**
*@param *array pointer to an array of integers
*@param elem int of the element to remove
* Removes an element 'elem' from the supplied integer array.
*/
void removeProcess(int *array, int elem) {
//Number of elements in the array
int numElem = sizeof(array) / sizeof(int);
int temparray[numElem - 1];
//Copy array to temparray except for elem to remove
int i;
for (i = 0; i < numElem; i++) {
if (i == elem) {
continue;
} else {
temparray[i] = array[i];
}
}
//End by setting the pointer of array to the temparray
array = temparray;
}
我知道分段错误来自sprintf。我试图模拟操作系统如何使用循环法完成一个过程。我尝试过使用sprintf,因为这是教程在尝试操作字符串时在线使用的内容。 removeProcessN只是从数组proNames中删除索引。我大多只关心sprintf。
我在做sprintf的时候尝试了malloc但是在那时它甚至都没有编译。如果有人可以提供解释我会很感激。
这里的问题是proNames
是一个指针数组,但它们是未初始化的,因此将它传递给sprintf
来写东西会崩溃。您可以使用双数组或使用malloc
分配内存。但是因为你只打印整数并且整数的字符串表示具有最大长度,所以用malloc
分配内存将更加困难,因为你必须检查malloc
不返回NULL
,你必须在以后释放内存,等等。
所以我会这样做:
char proNames[numPro][30]; // 28 characters for an int (usually 4 bytes long)
// should be more than enough
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
sprintf(proNames[i], "p%d", i);
}
你的removeProcessN
也需要改变:
void removeProcessN(int numElem, int elem, int dim, char (*array)[dim]) {
for(int i = elem; i < numElem - 1; ++i)
strcpy(array[i], array[i+1]);
array[numElem - 1][0] = 0; // setting last element to empty string
}
请注意,我在最后一个位置移动了array
参数,否则numElem
未知,编译器将返回错误。
现在你可以这样称呼它:
removeProcessN(elemNum, numPro, 30, proNames);
30来自char proNames[numProp][30];
宣言。
我想评论你的函数removeProcessN
的最后一行:
//End by setting the pointer of array to the temparray
array = temparray;
这是不正确的,首先是因为temparray
是局部变量,并且在函数返回时不再存在。并且array
是函数中的局部变量,因此更改它不会影响任何人。
内存分配的替代方案如下所示:
char *proNames[numPro];
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
int len = snprintf(NULL, 0, "p%d", i);
proNames[i] = malloc(len + 1);
if(proNames[i] == NULL)
{
// error handling, free the previously allocated
// memory, and return/exit
}
sprintf(proNames[i], "p%d", i);
}
和removeProcessN
:
void removeProcessN(char **array, int numElem, int elem) {
char *to_remove = array[elem];
for(int i = elem; i < numElem - 1; ++i)
array[i] = array[i+1];
free(to_remove);
array[numElem - 1] = NULL; // setting last element to NULL
// makes freeing easier as
// free(NULL) is allowed
}
你原来打电话给removeProcessN
的方式还可以。
如果你最终为所有进程调用removeProcessN
,那么应释放所有内存,因为removeProcessN
释放它。如果有一些元素保留在数组中,那么您必须在以后释放它们。
OP在评论中发布
我的理论是
temparray
将是指向array
的指针,所以我可以从主数组中删除索引。所以当我说array = temparray
时,数组的指针指向temparray。我知道它适用于removeProcess
。字符串有什么不同吗?
array = temparray
对removeProcess
也没有影响,array
仍然是一个局部变量,并且它所指向的地方变化根本没有效果,因为你只是改变一个局部变量。
除了代码错误:
int numElem = sizeof(array) / sizeof(int);
这仅适用于纯数组,它不适用于指针,因为sizeof(array)
返回需要存储int
指针的大小。与其他函数一样,您需要将数组的站点传递给函数。
如果你说这个函数有效,那么只是偶然,因为它会产生未定义的行为。通过错误地计算元素的数量,temparray
将具有错误的大小,因此在这里temparray[i] = array[i];
您可以访问超出界限,这导致未定义的行为。未定义的行为意味着您无法预测将要发生的事情,可能是从崩溃到格式化您的硬盘驱动器。由未定义的行为导致的结果是无用的。
再次array = temparray;
只是改变了局部变量array
指向的位置,removeProcess
的调用者没有看到。
正确的版本是:
int removeProcess(int *array, int elem, int numElem) {
if(array == NULL)
return 0;
// nothing to do if the elemnt to be removed is
// the last one
if(elem == numElem - 1)
return 1;
// overwriting the memory, because memory
// regions overlap, we use memmove
memmove(array + elem, array + elem + 1, numElem - elem - 1);
return 0;
}
所以,说清楚:
我们来看看这段代码:
void sum(int *array, size_t len);
{
int c[len];
array = c;
}
void bar(void)
{
int x[] = { 1, 3, 5 };
size_t len = sizeof x / sizeof *x;
sum(x, sizeof x / sizeof *x);
printf("x[0] = %d, x[1] = %d, x[2] = %d\n", x[0], x[1], x[2]);
}
sum
只有你在bar
传递的指针的副本,所以从bar
的角度来看,sum
改变了副本,所以bar
将打印x[0] = 1, x[1] = 3, x[2] = 5
。
但是,如果您希望调用者看到任何更改,那么您可以通过指针访问:
void sum(int *array, size_t len)
{
int c[len];
for(size_t i = 0; i < len; ++i)
array[i] += 10;
array = c;
}
有了这个版本,qazxsw poi将打印qazxsw poi和qazxsw poi将对bar
没有影响。