Note: Following code is causing memory corruption in process function input req is assigned to rsp. I didn't understand what happened here. after removing "rsp = req" then it is working. does this assignment will cause shallow copy of the structures in req?
does req and rsp structures are pointing same memory here?
struct info
{
uint8_t id;
uint64_t post_id;
uint64_t time_id;
};
struct updates
{
uint32_t id;
uint32_t fcn;
uint16_t icp;
uint64_t num_oh;
uint64_t num_rna;
bool is_rbn;
};
struct rbn_rel_info
{
uint16_t icp;
uint32_t fcn;
info relation;
uint32_t id_length;
uint32_t id;
};
struct rbn_info
{
uint16_t icp;
uint32_t fcn;
};
struct ind_info
{
info _info;
uint16_t num_rbn;
rbn_info _rbn_info[32];
uint16_t num_rel;
rbn_rel_info rel[32];
uint8_t nums;
updates _updates[32];
};
void process(struct ind_info req)
{
struct ind_info rsp = req;
//process req and send rsp
send_rsp(rsp);
}
int main()
{
struct ind_info req = {};
process(req);
return 0;
}
From this code I cannot see how a memory corruption could occur. The argument is passed by value and cannot corrupt any memory. There are no pointers in the structures either. The assignment as well, both use the compiler generated Trivial copy assignment operator.
The only reason I can think of is that something funny happens in send_rsp but I can't tell without looking at the code.
Related
I have a use case where one thread reads message into a large buffer and the distributes the processing to a bunch of threads. The buffer is shared by multiple threads after that. Its read-only and when the last thread finishes, the buffer has to be freed. The buffer is allocated from a lock-free slab allocator.
My initial design was to use shared_ptr for the buffer. But the buffer can be of different size. My way of getting around it was do something like this.
struct SharedBuffer {
SharedBuffer (uint16_t len, std::shared_ptr<void> ptr)
: _length(len), _buf(std::move(ptr))
{
}
uint8_t data () { return (uint8_t *)_buf.get(); }
uint16_t length
std::shared_ptr<void> _buf; // type-erase the shared_ptr as the SharedBuffer
// need to stored in some other structs
};
Now the allocator will allocate the shared_ptr like this:
SharedBuffer allocate (size_t size)
{
auto buf = std::allocate_shared<std::array<uint8_t, 16_K>>(myallocator);
return SharedBuffer{16_K, buf}; // type erase the std::array
}
And the SharedBuffer is enqueued to each thread who wants it.
Now I think, I am doing lot of stuff unnecessarily, I can sort of make do with boost::intrusive_ptr with the below scheme. Things are bit C'ish- as I am using variable size array. Here I have changed the slab allocator with a operator new() for the sake of simplicity. I wanted to run it by to see if this implementation is okay.
template <typename T>
inline int atomicIncrement (T* t)
{
return __atomic_add_fetch(&t->_ref, 1, __ATOMIC_ACQUIRE);
}
template <typename T>
inline int atomicDecrement (T* t)
{
return __atomic_sub_fetch(&t->_ref, 1, __ATOMIC_RELEASE);
}
class SharedBuffer {
public:
friend int atomicIncrement<SharedBuffer>(SharedBuffer*);
friend int atomicDecrement<SharedBuffer>(SharedBuffer*);
SharedBuffer(uint16_t len) : _length(len) {}
uint8_t *data ()
{
return &_data[0];
}
uint16_t length () const
{
return _length;
}
private:
int _ref{0};
const uint16_t _length;
uint8_t _data[];
};
using SharedBufferPtr = boost::intrusive_ptr<SharedBuffer>;
SharedBufferPtr allocate (size_t size)
{
// dummy implementation
void *p = ::operator new (size + sizeof(SharedBuffer));
// I am not explicitly constructing the array of uint8_t
return new (p) SharedBuffer(size);
}
void deallocate (SharedBuffer* sbuf)
{
sbuf->~SharedBuffer();
// dummy implementation
::operator delete ((void *)sbuf);
}
void intrusive_ptr_add_ref(SharedBuffer* sbuf)
{
atomicIncrement(sbuf);
}
void intrusive_ptr_release (SharedBuffer* sbuf)
{
if (atomicDecrement(sbuf) == 0) {
deallocate(sbuf);
}
}
I'd use the simpler implementation (using shared_ptr) unless you are avoiding specific problems (i.e. profile first).
Side Note: you can use boost::shared_pointer<> with boost::make_shared<T[]>(N), which is being [added to the standard library in c++20.
Note that allocate_shared already embeds the control block into the same allocation like you do with the intrusive approach.
Finally, I'd use std::atomic_int so you have a clear contract that cannot (accidentally) be used wrong. At the same time, it'll remove the remaining bit of complexity.
I'd like to assign std::string *ptr via stringstream::str() in C++.
I have a class below.
class A{
public:
A():ptr(nullptr){
}
void read(string& filename){ // this file contains a text.
std::ifstream ifs(filename);
std::stringstream ss;
ss << ifs;
*ptr=ss.str();
ifs.close();
}
private:
std::string *ptr;
};
int main(void){
A a();
std::string file="./file";
a.read(file);
return 0;
}
I expected that "*ptr" can be assigned by the text.
However, segmentation fault occurs at *ptr=ss.str().
How can I do that?
I think appending temporal object is one way to go as below.
//instead of *ptr=ss.str();
std::string str=ss.str();
ptr = &str;
But I dont want to create temporal object.
Thanks
You have to initialize your ptr to being able to dereference it. (and not to nullptr, which cannot de dereferenced obviously)
A() {
ptr = new std::string();
}
~A() {
delete ptr;
}
Also, assigning temporal variable is not a way to go, because after leaving the scope you will have garbage in your pointer
I'm working with a kernel driver for an I2C device and up until now I've been making simple attributes available using the sysfs DEVICE_ATTR helper. Now I need to make a long list of attributes available like /sys/bus/i2c/device/.../param0, .../param1, etc. but it seems inefficient to write a function for each one and maybe even the wrong use of the sysfs system. For example:
static DEVICE_ATTR(param0, S_IRUGO, NULL, foo_set_param0);
static DEVICE_ATTR(param1, S_IRUGO, NULL, foo_set_param1);
...
static DEVICE_ATTR(param50, S_IRUGO, NULL, foo_set_param50);
The values on the device change frequently and reading them is expensive so constantly reading them or using one function to read all of them is not really any option. I'm a bit of C newbie so maybe there is something totally obvious I'm missing, but can you use a wrapper on the sysfs show callback to take a parameter? Or is there a better system I should use for this? I looked at debugfs and it seems like I'd need to maintain the values in memory for it.
You can try container_of() macro. Simply fill your attribute data in a larger structure.
Here is an example for the creation of 100 attributes in a big structure big_kattr. The parameter is UNIT_NUM.
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#define UNIT_NUM 100
typedef struct {
struct kobj_attribute k_obj;
int num;
} big_kattr;
static struct kobject *register_kobj;
// rw functions
static ssize_t __used store_value(struct kobject *kp, struct kobj_attribute *attr, const char *buf, size_t count){
big_kattr *a = container_of(attr, big_kattr, k_obj);
sscanf(buf, "%du", &a->num);
return count;
}
static ssize_t show_value(struct kobject *kp, struct kobj_attribute *attr, char *buf) {
big_kattr *a = container_of(attr, big_kattr, k_obj);
return sprintf(buf, "%d\n", a->num);
}
// put attribute to attribute group
static struct attribute * unit_attrs[UNIT_NUM + 1];
static big_kattr full_unit_attrs[UNIT_NUM];
static struct attribute_group unit_attr_group;
static int hello_init(void){
int i;
memset(full_unit_attrs, 0, sizeof(full_unit_attrs));
memset(unit_attrs, 0, sizeof(unit_attrs));
memset(&unit_attr_group, 0, sizeof(unit_attr_group));
for(i=0; i<UNIT_NUM; i++){
char * str = kmalloc(32, GFP_KERNEL);
sprintf(str, "unit-%03d",i);
full_unit_attrs[i].k_obj.attr.name = str;
full_unit_attrs[i].k_obj.attr.mode = S_IWUSR | S_IRUGO;
full_unit_attrs[i].k_obj.show = show_value;
full_unit_attrs[i].k_obj.store = store_value;
full_unit_attrs[i].num = i;
unit_attrs[i] = &(full_unit_attrs[i].k_obj.attr);
}
unit_attr_group.attrs = unit_attrs;
// create sysfs object ( /sys/kernel/many directory )
register_kobj = kobject_create_and_add("many", kernel_kobj);
if (!register_kobj)
return -ENOMEM;
//create all attributes (files)
if(sysfs_create_group(register_kobj, &unit_attr_group)){
kobject_put(register_kobj);
return -ENOMEM;
}
return 0;
}
static void hello_exit(void){
int i;
kobject_put(register_kobj);
for(i=0; i<UNIT_NUM; i++)
kfree(full_unit_attrs[i].k_obj.attr.name);
}
MODULE_LICENSE("Dual BSD/GPL");
module_init(hello_init);
module_exit(hello_exit);
Example:
cat /sys/kernel/many/unit-077
echo 12345 > /sys/kernel/many/unit-088
cat /sys/kernel/many/unit-088
I have a memory location a and I want to copy a certain amount of bytes to another location fast, how would I do this in D ?
For example how would i do this:
int main()
{
void* src_data = 0x40001255;
void* dst_data = 0x47F22000;
u32 size = 0x200;
memcpy(dst_data, src_data, size);
}
Also how would fill a struct fast:
struct data_struct
{
u32 block1;
u32 block2;
u32 block3;
u32 block4;
u32 block5;
u62 block6;
u128 bigblock;
} data_struct_t;
int main()
{
void* src_data = 0x40001255;
struct data_struct_t dst_data;
u32 size = sizeof(data_struct);
memcpy(dst_data, src_data, size);
}
Thanks!
Roel
Assigning to a slice will perform an array copy, which calls memcpy internally.
void main()
{
void* src_data = 0x40001255;
void* dst_data = 0x47F22000;
uint size = 0x200;
dst_data[0..size] = src_data[0..size];
}
For the second one:
struct data_struct
{
uint block1, block2, block3, block4, block5;
ulong block6;
uint[4] bigblock;
}
void main()
{
auto src_data = cast(data_struct*) 0x40001255; // unaligned, WTF?!
auto dst_data = *src_data;
}
Note that you also have access to C's memcpy in D. D can directly access C's whole standard library.
I working on some code in the linux kernel (2.4) and for some reason kmalloc returns the same address (I believe it only happens after the middle of the test). I checked that no calls to kfree were made between the calls to kmalloc (i.e memory is still in use).
maybe I'm out of memory ? (kmalloc didn't return NULL...)
any ideas on how such a thing can happen ?
thanks in advance for the help!
code:
typedef struct
{
char* buffer;
int read_count;
int write_count;
struct semaphore read_sm;
struct semaphore write_sm;
int reader_ready;
int writer_ready;
int createTimeStamp;
} data_buffer_t ;
typedef struct vsf_t vsf_t;
struct vsf_t
{
int minor;
int type;
int open_count;
int waiting_pid;
data_buffer_t* data;
list_t proc_list;
vsf_t* otherSide_vsf;
int real_create_time_stamp;
};
int create_vsf(struct inode *inode, struct file *filp, struct vsf_command_parameters* parms)
{
...
buff_data = allocate_buffer();
if (buff_data == NULL)
{
kfree(this_vsfRead);
kfree(this_vsfWrite);
return -ENOMEM;
}
...
}
data_buffer_t* allocate_buffer()
{
...
data_buffer_t* this_buff = (data_buffer_t*)kmalloc(sizeof(data_buffer_t), GFP_KERNEL);
if (this_buff == NULL)
{
printk( KERN_WARNING "failure at allocating memory\n" );
return NULL;
}
...
return this_buff;
}
*I print after every kmalloc and kfree,I'm absolutely sure that no kfree is called between kmalloc's (that return the same adress)
I don't know what kmalloc's data structures look like but you could imagine this happening if a previous double free caused a cycle in a linked list of buffers. Further frees could still chain on additional distinct buffers (able to be reallocated) but once those were exhausted that last buffer would be returned indefinitely.