C 如何通过反馈从缓冲区读取,因此';缓冲区溢出?
我有这个密码C 如何通过反馈从缓冲区读取,因此';缓冲区溢出?,c,buffer-overflow,C,Buffer Overflow,我有这个密码 #define BUFFER_LEN (2048) static float buffer[BUFFER_LEN]; int readcount; while ((readcount = sf_read_float(handle, buffer, BUFFER_LEN))) { // alsa play } 它从缓冲区读取缓冲区浮点数,并返回实际读取的浮点数。“句柄”告诉sf_rad_float缓冲区有多大 例如,如果缓冲区包含5个浮点数,且缓冲区长度为3,readcoun
#define BUFFER_LEN (2048)
static float buffer[BUFFER_LEN];
int readcount;
while ((readcount = sf_read_float(handle, buffer, BUFFER_LEN))) {
// alsa play
}
它从缓冲区读取缓冲区浮点数,并返回实际读取的浮点数。“句柄”告诉sf_rad_float缓冲区有多大
例如,如果缓冲区包含5个浮点数,且缓冲区长度为3,readcount将首先返回3,下一次返回2,while循环将退出
我想有一个函数,做同样的事情
更新
经过大量的编码,我认为这就是解决方案
#include <stdio.h>
int copy_buffer(double* src, int src_length, int* src_pos,
float* dest, int dest_length) {
int copy_length = 0;
if (src_length - *src_pos > dest_length) {
copy_length = dest_length;
printf("copy_length1 %i\n", copy_length);
} else {
copy_length = src_length - *src_pos;
printf("copy_length2 %i\n", copy_length);
}
for (int i = 0; i < copy_length; i++) {
dest[i] = (float) src[*src_pos + i];
}
// remember where to continue next time the copy_buffer() is called
*src_pos += copy_length;
return copy_length;
}
int main() {
double src[] = {1,2,3,4,5};
int src_length = 5;
float dest[] = {0,0};
int dest_length = 2;
int read;
int src_pos = 0;
read = copy_buffer(src, src_length, &src_pos, dest, dest_length);
printf("read %i\n", read);
printf("src_pos %i\n", src_pos);
for (int i = 0; i < src_length; i++) {
printf("src %f\n", src[i]);
}
for (int i = 0; i < dest_length; i++) {
printf("dest %f\n", dest[i]);
}
return 0;
}
#包括
int copy_缓冲区(双*src,int src_长度,int*src_位置,
浮动*dest,int dest_长度){
int copy_length=0;
if(src_长度-*src_位置>目的地长度){
复制长度=目的地长度;
printf(“复制长度1%i\n”,复制长度);
}否则{
复制长度=src长度-*src位置;
printf(“复制长度2%i\n”,复制长度);
}
对于(int i=0;i
下次调用copy_buffer()时,dest包含3,4。再次运行copy\u buffer()
仅复制值“5”。所以我认为它现在起作用了
虽然它不是很漂亮,但是我有intsrc_pos=0代码>外部打开复制缓冲区()
如果我能给copy\u buffer()
一个唯一的句柄,而不是像sndfile那样给&src\u pos
,那会好得多
有人知道如何做到这一点吗?我开始研究它,但你可能也可以这么做:libsndfile是开源的,所以你可以看看sf\u read\u float()
是如何工作的,并创建一个从缓冲区执行相同操作的函数。有一个下载链接。如果要创建唯一句柄,可以使用malloc()
和struct
:
typedef intptr_t HANDLE_TYPE;
HANDLE_TYPE init_buffer_traverse(double * src, size_t src_len);
int copy_buffer(HANDLE_TYPE h_traverse, double * dest, size_t dest_len);
void close_handle_buffer_traverse(HANDLE_TYPE h);
typedef struct
{
double * source;
size_t source_length;
size_t position;
} TRAVERSAL;
#define INVALID_HANDLE 0
有一些明显的区别。C++版本看起来有点冗长。其中一些是虚幻的;C++的对象等价于当然,delete
不是TRAVERSAL
类实现的一部分,delete
与该语言一起提供
在C++版本中,没有“不透明”句柄。
C版本更加明确,并且可能使硬件在响应程序执行时执行的操作更加明显
C版本更易于使用cast toHANDLE_TYPE
来创建“不透明ID”,而不是指针类型。C++版本可以“打包”在API中,在添加另一层时,实现相同的API。在当前示例中,该类的用户将维护一个遍历*
的副本,该副本不太“不透明”
在函数<代码> CopyBuffel()/Cuff>中,C++版本不必提及<代码> TRAV < /Cult>指针,因为它隐含地取消了编译器提供的<代码> < <代码>指针> < /P>
> SigeOf(TraceOver)/Cux>对于C和C++示例都应该是相同的——没有VTABLE,也假设C++运行时类型标识被关闭,C++类只包含与我们第一个例子中的C结构相同的内存布局。
<> >在C++中使用“不透明ID”样式较不常见,因为C++中“透明度”的惩罚被降低。类遍历
的数据成员是私有的
,因此遍历*
不能意外地用于破坏我们与API用户的API合同
请注意,不透明ID和类指针都容易被恶意API用户滥用——不透明ID或类指针都可以直接强制转换到,例如,double**
,允许ID持有者通过内存直接更改源
成员。当然,您必须已经信任API调用方,因为在这种情况下,API调用代码位于相同的地址空间中。在网络文件服务器的示例中,如果将基于内存地址的“不透明ID”暴露给外部,则可能存在安全隐患
我通常不会把API转换成信任度,但是我想澄清C++关键字>代码>私有< /C>没有“强制力”,它只规定程序员之间的一个协议,编译器也尊重它,除非人类告诉它。
最后,C++类指针可以转换为不透明的ID:
typedef intptr_t HANDLE_TYPE;
HANDLE_TYPE init_buffer_traverse(double *src, size_t src_len)
{
return (HANDLE_TYPE)(new TRAVERSAL(src, src_len));
}
int copy_buffer(HANDLE_TYPE h_traverse, double * dest, size_t dest_len)
{
return ((TRAVERSAL *)h_traverse)->copy_buffer(dest, dest_len);
}
void close_handle_buffer_traverse(HANDLE_TYPE h)
{
delete ((TRAVERSAL *)h);
}
现在我们对“等价”C++的简洁性可能会受到进一步质疑。
我写的关于C++编程的旧风格并不是说C++更适合这个任务。我只是说,封装数据和隐藏实现细节可以通过C语言来完成,它的风格几乎与C++风格同构。如果你发现自己在C中编程,但很遗憾,首先学习C++,这是很好的。
PS
我刚刚注意到,到目前为止,我们的实施使用了:
dest[i] = (float)source[position + i];
当复制字节时。因为dest
和source
都是double*
(也就是说,它们都指向double
值),所以这里不需要强制转换。此外,从double
到float
的转换可能会丢失浮点表示中的精度位数。所以这是最好的选择
int copy_buffer(HANDLE_TYPE h,
float* dest, int dest_length)
{
TRAVERSAL * trav = NULL;
if (INVALID_HANDLE == h)
return -1;
trav = (TRAVERSAL *)h;
int copy_length = trav->source_length - trav->position;
if (dest_length < copy_length)
copy_length = dest_length;
for (int i = 0; i*emphasized text* < copy_length; i++)
dest[i] = trav->source[trav->position + i];
// remember where to continue next time the copy_buffer() is called
trav->position += copy_length;
return copy_length;
}
class TRAVERSAL
{
double * source;
size_t source_length;
size_t position;
public TRAVERSAL(double *src, size_t src_len)
{
source = src;
source_length = src_len;
position = 0;
}
public int copy_buffer(double * dest, size_t dest_len)
{
int copy_length = source_length - position;
if (dest_length < copy_length)
copy_length = dest_length;
for (int i = 0; i < copy_length; i++)
dest[i] = source[position + i];
// remember where to continue next time the copy_buffer() is called
position += copy_length;
return copy_length;
}
}
typedef intptr_t HANDLE_TYPE;
HANDLE_TYPE init_buffer_traverse(double *src, size_t src_len)
{
return (HANDLE_TYPE)(new TRAVERSAL(src, src_len));
}
int copy_buffer(HANDLE_TYPE h_traverse, double * dest, size_t dest_len)
{
return ((TRAVERSAL *)h_traverse)->copy_buffer(dest, dest_len);
}
void close_handle_buffer_traverse(HANDLE_TYPE h)
{
delete ((TRAVERSAL *)h);
}
dest[i] = (float)source[position + i];
dest[i] = source[position + i];