实现 createArray
和 destroyArray
函数
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *data;
int size;
} ArrayWrapper;
ArrayWrapper* createArray(int n) {
ArrayWrapper *wrapper = (ArrayWrapper*)malloc(sizeof(ArrayWrapper));
if (wrapper == NULL) {
return NULL;
}
wrapper->data = (int*)malloc(n * sizeof(int));
if (wrapper->data == NULL) {
free(wrapper);
return NULL;
}
wrapper->size = n;
return wrapper;
}
void destroyArray(ArrayWrapper* wrapper) {
if (wrapper != NULL) {
free(wrapper->data);
free(wrapper);
}
}
内存管理问题及避免方法
- 内存泄漏:
- 问题:在
createArray
函数中,如果 malloc
分配内存失败,而之前已经分配了部分内存(如 wrapper
分配成功但 wrapper->data
分配失败),若不释放已分配的内存,就会导致内存泄漏。
- 避免方法:如上述代码,在
wrapper->data
分配失败时,及时释放 wrapper
。在 destroyArray
函数中,确保在释放 wrapper->data
后释放 wrapper
结构体本身。
- 悬空指针:
- 问题:如果在调用
destroyArray
释放内存后,没有将指针设置为 NULL
,而后续代码误操作该指针,就会产生悬空指针,导致未定义行为。
- 避免方法:在
destroyArray
释放内存后,将指向 ArrayWrapper
的指针设置为 NULL
。例如:
ArrayWrapper *wrapper = createArray(10);
destroyArray(wrapper);
wrapper = NULL;
- 双重释放:
- 问题:如果多次调用
destroyArray
对同一 ArrayWrapper
指针进行释放,会导致双重释放错误,程序崩溃。
- 避免方法:在释放指针后将其设置为
NULL
,如上述避免悬空指针的方法。另外,可以在代码逻辑上确保不会重复调用释放函数。
多线程环境下的常见误区和问题及解决方法
- 数据竞争:
- 问题:多个线程同时访问和修改
ArrayWrapper
中的 data
数组或 size
成员,可能导致数据不一致。例如,一个线程正在读取 data
数组时,另一个线程对其进行修改。
- 解决方法:使用互斥锁(
pthread_mutex_t
)来保护对 ArrayWrapper
的访问。例如:
#include <pthread.h>
pthread_mutex_t wrapperMutex = PTHREAD_MUTEX_INITIALIZER;
ArrayWrapper* createArray(int n) {
pthread_mutex_lock(&wrapperMutex);
ArrayWrapper *wrapper = (ArrayWrapper*)malloc(sizeof(ArrayWrapper));
if (wrapper == NULL) {
pthread_mutex_unlock(&wrapperMutex);
return NULL;
}
wrapper->data = (int*)malloc(n * sizeof(int));
if (wrapper->data == NULL) {
free(wrapper);
pthread_mutex_unlock(&wrapperMutex);
return NULL;
}
wrapper->size = n;
pthread_mutex_unlock(&wrapperMutex);
return wrapper;
}
void destroyArray(ArrayWrapper* wrapper) {
if (wrapper != NULL) {
pthread_mutex_lock(&wrapperMutex);
free(wrapper->data);
free(wrapper);
pthread_mutex_unlock(&wrapperMutex);
}
}
- 死锁:
- 问题:如果多个线程以不同顺序获取多个互斥锁,可能会导致死锁。例如,线程A获取锁1,然后尝试获取锁2,而线程B获取锁2,然后尝试获取锁1。
- 解决方法:使用锁顺序规则,确保所有线程以相同顺序获取互斥锁。另外,可以使用死锁检测工具来发现潜在的死锁问题。
- 条件变量使用不当:
- 问题:如果在使用条件变量(
pthread_cond_t
)时没有正确与互斥锁配合,可能导致线程永远等待或误唤醒。
- 解决方法:在等待条件变量时,必须持有相关的互斥锁。在条件满足时,使用
pthread_cond_signal
或 pthread_cond_broadcast
唤醒等待的线程,并确保在唤醒线程后,线程能够正确获取互斥锁并处理数据。例如:
pthread_cond_t dataReadyCond = PTHREAD_COND_INITIALIZER;
// 假设某个线程填充数组
void* fillArray(void* arg) {
ArrayWrapper *wrapper = (ArrayWrapper*)arg;
// 填充数组
pthread_mutex_lock(&wrapperMutex);
// 通知其他线程数据已准备好
pthread_cond_signal(&dataReadyCond);
pthread_mutex_unlock(&wrapperMutex);
return NULL;
}
// 假设某个线程读取数组
void* readArray(void* arg) {
ArrayWrapper *wrapper = (ArrayWrapper*)arg;
pthread_mutex_lock(&wrapperMutex);
// 等待数据准备好
pthread_cond_wait(&dataReadyCond, &wrapperMutex);
// 读取数组
pthread_mutex_unlock(&wrapperMutex);
return NULL;
}